web-dev-qa-db-ja.com

Active Record、RailsおよびPostgresで複数の重複フィールドを持つ行を検索します

PostgresとActiverecordを使用して、複数の列にわたって重複値を持つレコードを見つける最良の方法は何ですか?

私はこの解決策を見つけました ここ

User.find(:all, :group => [:first, :email], :having => "count(*) > 1" )

しかし、postgresでは動作しないようです。私はこのエラーを受け取っています:

PG :: GroupingError:ERROR:列 "parts.id"は、GROUP BY句に含まれているか、集計関数で使用されている必要があります

91
newUserNameHere

テスト済みおよび動作中のバージョン

User.select(:first,:email).group(:first,:email).having("count(*) > 1")

また、これは少し無関係ですが便利です。各組み合わせが検出された時間を確認するには、末尾に.sizeを入力します。

User.select(:first,:email).group(:first,:email).having("count(*) > 1").size

次のような結果セットが返されます。

{[nil, nil]=>512,
 ["Joe", "[email protected]"]=>23,
 ["Jim", "[email protected]"]=>36,
 ["John", "[email protected]"]=>21}

それはかなりクールだと思ったし、それを見たことがなかった。

Tarynに感謝します。これは、彼女の答えを微調整したバージョンです。

189
newUserNameHere

このエラーは、POSTGRESでグループ化列をSELECT句に含める必要があるために発生します。

試してください:

User.select(:first,:email).group(:first,:email).having("count(*) > 1").all

(注:テストされていないため、微調整する必要がある場合があります)

Id列を削除するように編集されました

28
Taryn East

完全なモデルが必要な場合は、次を試してください(@newUserNameHereの答えに基づいて)。

User.where(email: User.select(:email).group(:email).having("count(*) > 1").select(:email))

これにより、行の電子メールアドレスが一意でない行が返されます。

複数の属性に対してこれを行う方法を知りません。

7
Ben Aubin

PostgreSQLを使用する場合、単一クエリですべての重複を取得します。

def duplicated_users
  duplicated_ids = User
    .group(:first, :email)
    .having("COUNT(*) > 1")
    .select('unnest((array_agg("id"))[2:])')

  User.where(id: duplicated_ids)
end

irb> duplicated_users
0
itsnikolay