如何使用Active Record查找具有重复数据的记录

29

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


仅有1列重复值还是多列?这些是字符串/整数/文本字段吗? - Danny Hiemstra
字符串 - srboisvert
6个回答

51

将 @TuteC 翻译成 ActiveRecord:

sql = 'SELECT id, 
         COUNT(id) as quantity 
         FROM types 
         GROUP BY name 
       HAVING quantity > 1'
#=>
Type.select("id, count(id) as quantity")
  .group(:name)
  .having("quantity > 1")

7
这段代码是否也适用于PostgreSQL?它返回了错误信息 PGError: ERROR: column "quantity" does not exist - Marc
6
@Marc,我不确定。但是你可以尝试Type.select("id, count(id) as quantity").group(:name).having("count(id) > 1") - fl00r
3
"非精确副本"是什么意思,可以准确解释一下吗?(双关语) - Javid Jamae
1
Postgresql - ActiveRecord::StatementInvalid: PG::GroupingError: 错误:列“types.id”必须出现在GROUP BY子句中或在聚合函数中使用。但是,将其添加到group-by中(没有错误),然后您会得到零个命中,因为没有两个记录具有相同的id值。我尝试了几种解决方案,所有这些解决方案要么不在结果中返回ID(因此谁知道重复项在哪里),要么在包括ID时无法找到所需的记录。 - JosephK
最佳解决方法在这里:https://dev59.com/TJDea4cB1Zd3GeqPcX0K 适应于此的是:type_dups = Type.group(:name).having("count(name) > 1").count.keys; @results = Type.where(:name => type_dups) - JosephK
显示剩余3条评论

28

以下是我使用AREL助手解决它的方法,没有使用自定义SQL:

Person.select("COUNT(last_name) as total, last_name")
  .group(:last_name)
  .having("COUNT(last_name) > 1")
  .order(:last_name)
  .map{|p| {p.last_name => p.total} }

实际上,这只是一种更好的编写 SQL 语句的方式。它可以找到所有具有重复 last_name 值的记录,并以漂亮的哈希形式告诉您有多少个以及它们的姓氏是什么。


19

我在使用2016年的技术栈(Rails 4.2,Ruby 2.2)时遇到了一个难题,最终通过以下方法解决:

> Model.select([:thing]).group(:thing).having("count(thing) > 1").all.size
 => {"name1"=>5, "name2"=>4, "name3"=>3, "name4"=>2, "name5"=>2}

3
这正是我所需要的。 - Paul Brunache

11

使用自定义 SQL,可以查找具有相同 name 值的 types

sql = 'SELECT id, COUNT(id) as quantity FROM types
         GROUP BY name HAVING quantity > 1'
repeated = ActiveRecord::Base.connection.execute(sql)

5
在Rails 2.x中,select是AR类的私有方法。只需使用find():
klass.find(:all, 
  :select => "id, count(the_col) as num", 
  :conditions => ["extra conditions here"], 
  :group => 'the_col', 
  :having => "num > 1")

3
这完全不相关,有点像挖坟的评论...但为什么这比SQL更好呢?(原文已翻译,无需修改) - John Cromartie
@JohnCromartie 不是啦。不过挺好玩的。;) - Nowaker

2

这里提供了一种解决方案,扩展了其他答案,以显示如何查找和迭代按重复字段分组的记录:

duplicate_values = Model.group(:field).having(Model.arel_table[:field].count.gt(1)).count.keys
Model.where(field: duplicate_values).group_by(&:field).each do |value, records|
  puts "The records with ids #{records.map(&:id).to_sentence} have field set to #{value}"
end

看起来需要用两个查询来完成这个操作,但这个回答证实了这种方法。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接