如何以编程方式查找这些重复记录?

时间:2012-01-09 21:30:59

标签: sql ruby-on-rails ruby ruby-on-rails-3 duplicates

我有一些实例,其中创建了一些重复记录,现在我需要清理它们,因为我已经找出了导致它们的原因。

我有ResponseSets和每个ResponseSet has_many Responses

每个Response都有answer_id的值,而answer_id只应出现ResponseSet一次。

所以我需要做的是根据同一个Responses中是否有多个ResponseSet,为每个answer_id找到重复的{{1}}。

我的大脑很难解释,所以如果需要更多细节,请问问。

2 个答案:

答案 0 :(得分:3)

尝试这样的事情:

ResponseSets.all.each do |set|
  answer_ids = []
  set.responses.each do |r|
    puts "Response #{r.id}: set=#{set.id}, answer=#{r.answer_id}"
    if answer_ids.include? r.answer_id
      puts "Duplicate found!"
      # r.destroy  # Uncomment when you feel it is safe
    else
      answer_ids << r.answer_id
    end
  end
end

答案 1 :(得分:3)

这应该为您提供具有重复项的对象的ID。

select rs.id, r.answer_id, count(r.id)
from response_sets rs
join responses r on r.response_set_id = rs.id
group by rs.id, r.answer_id
having count(r.id) > 1;

此查询返回ResponseSets的ID(rs.id)表,其中答案数r.answer_id的响应数等于count(r.id)。我们只对重复项感兴趣,因此我们采用那些count(r.id) > 1

现在,让我们通过将上面的查询包装在另一个select中来获取实际的响应ID。

select r.id
from responses r
join (
  select rs.id as rs_id, r.answer_id as a_id, r.id as r_id
  from response_sets rs
  join responses r on r.response_set_id = rs.id
  group by rs.id, r.answer_id
  having count(r.id) > 1
) on r.response_set_id = rs_id
where r.answer_id = a_id and r.id != r_id;

我们在这里有什么?我们采用从前一个查询中获得的内容,并询问其answer_id等于给定ResponseSet中已知重复项的答案ID的响应的ID。由于它将在ResponseSet中返回具有给定answer_id所有响应,因此我们可能希望通过添加and r.id != r_id来仅选择重复项。删除此谓词并查看它如何更改返回的集合。

它是纯SQL,所以它应该比通过ORM的多个查询更快。您可以考虑在外键response_set_id上添加索引,但如果不对实际数据进行基准测试或查看查询执行计划,则很难确定。