使用Active Record,Rails和amp;查找具有多个重复字段的行Postgres的

时间:2014-02-10 04:39:30

标签: ruby-on-rails postgresql activerecord

使用Postgres和Activerecord在多列中查找具有重复值的记录的最佳方法是什么?

我找到了这个解决方案here

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

但它似乎不适用于postgres。我收到了这个错误:

PG :: GroupingError:错误:列“parts.id”必须出现在GROUP BY子句中或用于聚合函数

5 个答案:

答案 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