PostgresとActiverecordを使用して、複数の列にわたって重複値を持つレコードを見つける最良の方法は何ですか?
私はこの解決策を見つけました ここ :
User.find(:all, :group => [:first, :email], :having => "count(*) > 1" )
しかし、postgresでは動作しないようです。私はこのエラーを受け取っています:
PG :: GroupingError:ERROR:列 "parts.id"は、GROUP BY句に含まれているか、集計関数で使用されている必要があります
テスト済みおよび動作中のバージョン
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に感謝します。これは、彼女の答えを微調整したバージョンです。
このエラーは、POSTGRESでグループ化列をSELECT句に含める必要があるために発生します。
試してください:
User.select(:first,:email).group(:first,:email).having("count(*) > 1").all
(注:テストされていないため、微調整する必要がある場合があります)
Id列を削除するように編集されました
完全なモデルが必要な場合は、次を試してください(@newUserNameHereの答えに基づいて)。
User.where(email: User.select(:email).group(:email).having("count(*) > 1").select(:email))
これにより、行の電子メールアドレスが一意でない行が返されます。
複数の属性に対してこれを行う方法を知りません。
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