2011-04-12 55 views
3

我有如下表:如何使用Rails刪除MySQL中的重複項?

關係

[id,user_id,status] 
1,2,sent_reply 
1,2,sent_mention 
1,3,sent_mention 
1,4,sent_reply 
1,4,sent_mention 

我正在尋找一種方式來刪除重複的,因此,只有以下行將保持:

1,2,sent_reply 
1,3,sent_mention 
1,4,sent_reply 

(最好使用Rails)

+0

你想只返回uniq項目,或者你想刪除所有重複? – fl00r 2011-04-12 16:33:02

+0

同樣你的所有關係都有相同的ID – fl00r 2011-04-12 16:34:45

+0

所以你只需要一個單一的(id,user_id)對,不管狀態如何?你如何決定保留哪些「狀態」信息?最後一個記錄?第一?隨機? – 2011-04-12 16:44:31

回答

-1

最好通過SQL來完成。但是,如果你喜歡用Rails:

(Relation.all - Relation.all.uniq_by{|r| [r.user_id, r.status]}).each{ |d| d.destroy } 

ids = Relation.all.uniq_by{|r| [r.user_id, r.status]}.map(&:id) 
Relation.where("id IS NOT IN (?)", ids).destroy_all # or delete_all, which is faster 

,但我不喜歡這樣的解決方案:d

+0

這將是非常緩慢和消耗內存(我的關係表是100,000+行。有沒有更多的SQLish方式來做到這一點,在這一點上,它不是很重要的包裝它在軌道。 – MikeMarsian 2011-04-14 09:33:33

3

我知道這是遲到的方式,但我發現一個好辦法使用Rails 3來完成它。然而,有可能有更好的方法,但我不知道這將如何執行100,000行以上的數據,但這應該讓你走上正軌。

# Get a hash of all id/user_id pairs and how many records of each pair 
counts = ModelName.group([:id, :user_id]).count 
# => {[1, 2]=>2, [1, 3]=>1, [1, 4]=>2} 

# Keep only those pairs that have more than one record 
dupes = counts.select{|attrs, count| count > 1} 
# => {[1, 2]=>2, [1, 4]=>2} 

# Map objects by the attributes we have 
object_groups = dupes.map do |attrs, count| 
    ModelName.where(:id => attrs[0], :user_id => attrs[1]) 
end 

# Take each group and #destroy the records you want. 
# Or call #delete instead to save time if you don't need ActiveRecord callbacks 
# Here I'm just keeping the first one I find. 
object_groups.each do |group| 
    group.each_with_index do |object, index| 
    object.destroy unless index == 0 
    end 
end