2012-05-02 33 views
0

特定の日付に複数のレコードがある場合、その日の最新のレコードを除くすべてのレコードを削除します。たとえば、IDが9、10、12のテーブルレコードは同じ日付です。したがって、ID12が最新の日付を持つレコードとして9と10を削除する必要があります。ここでActiveRecord:重複レコードを削除する

id  date 
1 2012-04-25 00:00:00.000000 
2 2012-04-26 00:00:00.000000 
3 2012-04-23 00:00:00.000000 
4 2012-04-24 00:00:00.000000 
5 2012-05-01 00:00:00.000000 
6 2012-05-02 00:00:00.000000 
7 2012-05-03 00:00:00.000000 
8 2012-05-04 00:00:00.000000 
9 2012-04-30 00:30:00.000000 
10 2012-04-30 18:00:00.000000 
11 2012-04-29 00:00:00.000000 
12 2012-04-30 18:40:00.000000 
13 2012-05-05 00:00:00.000000 
14 2012-05-05 09:31:31.000000 

重複を削除する(汚い)rakeタスク

task :remove_duplicate do 
    Rake::Task["remove_duplicate"].invoke 
end 

task :remove_duplicate => :environment do 
    weights = Weight.count(:group => "DATE(date)", :having => "COUNT(id) > 1") 
    weights_to_delete = [] 
    weights.each do |weight| 

    start_date = weight[0].to_date.beginning_of_day 
    end_date = weight[0].to_date.end_of_day 
    day_weights = Weight.where("date >= ? and date <= ?", start_date, end_date).order(:date) 
    day_weights[0..-2].each do |weight| 
     weights_to_delete.push weight.id 
    end 
    end 
    Weight.delete(weights_to_delete) 
end 

私は、私が説明したようにレコードを削除することができていますが、私は私が取るアプローチに満足していないです。 ActiveRecord APIをより有効に活用して最新のものを保持して、特定の日付に重複したレコードを削除するよう指示してください。

おかげで、アミットパテル

答えて

0

はこれを試してみてください:

latest_daily_weights = (Weight.maximum :date, :group => 'DATE(date)').values 
weights_table = Arel::Table.new(:weights) 
earlier_daily_weights = Weight.where(weights_table[:date].not_in latest_daily_weights) 
earlier_daily_weights.delete_all 

クレジット:この方法は遅くなる可能性が

How to exclude an array of ids from query in Rails (using ActiveRecord)?

4

あなたが実行している場合を除きので、私はそれをお勧めしません。それは定期的です。

Weight.all.each do |weight| 
    Weight.order("id desc").where(date: weight.date).all.drop(1).each { |w| w.delete } 
end 
+0

が、私は1回限りの操作として使用されるとき、それは仕事をしたし、速度の前に明確に理解できるコードを読むことを好む。 – lime

0

あなたは、このSQLクエリを試すことができ、同じ日付のレコードを削除することではなく、最新のその日に1ゆっくりと着実

DELETE FROM weights USING weights weight WHERE (CAST(weights.date as Date) = CAST(weight.date as Date) AND weights.id < weight.id); 
関連する問題