使用Postgres和Activerecord在多列中查找具有重复值的记录的最佳方法是什么?
我找到了这个解决方案here:
User.find(:all, :group => [:first, :email], :having => "count(*) > 1" )
但它似乎不适用于postgres。我收到了这个错误:
PG :: GroupingError:错误:列“parts.id”必须出现在GROUP BY子句中或用于聚合函数
答案 0 :(得分:177)
经测试&工作版
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", "test@test.com"]=>23,
["Jim", "email2@gmail.com"]=>36,
["John", "email3@gmail.com"]=>21}
认为这很酷,之前没见过。
归功于Taryn,这只是她答案的调整版本。
答案 1 :(得分:26)
发生该错误是因为POSTGRES要求您在SELECT子句中放置分组列。
尝试:
User.select(:first,:email).group(:first,:email).having("count(*) > 1").all
(注意:未经测试,您可能需要调整它)
已删除以删除ID列
答案 2 :(得分:6)
如果您需要完整型号,请尝试以下操作(基于@ newUserNameHere的答案)。
User.where(email: User.select(:email).group(:email).having("count(*) > 1").select(:email))
这将返回行的电子邮件地址不唯一的行。
我不知道在多个属性上执行此操作的方法。
答案 3 :(得分:0)
如果使用 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
答案 4 :(得分:-1)
基于answer above @newUserNameHere我相信显示每个人的计数的正确方法是
res = User.select('first, email, count(1)').group(:first,:email).having('count(1) > 1')
res.each {|r| puts r.attributes } ; nil