我有一些实例,其中创建了一些重复记录,现在我需要清理它们,因为我已经找出了导致它们的原因。
我有ResponseSets
和每个ResponseSet has_many Responses
。
每个Response
都有answer_id
的值,而answer_id
只应出现ResponseSet
一次。
所以我需要做的是根据同一个Responses
中是否有多个ResponseSet
,为每个answer_id
找到重复的{{1}}。
我的大脑很难解释,所以如果需要更多细节,请问问。
答案 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
上添加索引,但如果不对实际数据进行基准测试或查看查询执行计划,则很难确定。