これは、各パスで、map_id
当たり単一の複製を選択する、波のように重複を破壊します。重複が存在しなくなると、ループは自動的に終了します。
loop do
duplicates = Summary.select("MAX(id) as id, map_id").group(:map_id).having("count(*) > 1")
break if duplicates.length == 0
duplicates.destroy_all
end
データベースは次のようになります場合:最初の波で
| id | map_id |
| 1 | 235 |
| 2 | 299 |
| 3 | 324 |
| 4 | 235 |
| 5 | 235 |
| 6 | 299 |
| 7 | 235 |
| 8 | 324 |
| 9 | 299 |
、これらのレコードが返され、破壊される:第二波で
| id | map_id |
| 7 | 235 |
| 8 | 324 |
| 9 | 299 |
、このレコードは次のようになります返され、破壊された:
| id | map_id |
| 5 | 235 |
| 6 | 299 |
第三の波は、このレコードを返し、破壊するであろう:
| id | map_id |
| 4 | 235 |
第四の波は、プロセスを完了します。与えられたmap_id
に対して多数の重複がない限り、このプロセスは1桁のループ反復で終了する可能性があります。
このアプローチでは、重複のみが返され、より新しいの重複が削除されます。古い重複、代わりに、クエリがこれに変更することができます削除するには:その場合は
duplicates = Summary.select("MIN(id) as id, map_id").group(:map_id).having("count(*) > 1")
を、波1が戻って破壊するであろう:
| id | map_id |
| 1 | 235 |
| 2 | 299 |
| 3 | 324 |
ウェーブ2は戻って破壊するであろう:
| id | map_id |
| 4 | 235 |
| 6 | 299 |
ウェーブ3は戻って破壊するであろう:
| id | map_id |
| 5 | 235 |
Wave 4が処理を完了します。
SQLの周りであなたのやり方を知っているのであれば、SQLでやってみませんか? –
なんらかの理由で、私は純粋なSQLをレールに使用するのが難しいと思っていました。私はこれをSQLで数回しました。 1つはmap_idによって順序付けられ、最初に選択されます。他の方法は、order by、countカラムの作成、countカラム= some_number(最初のものではなく2番目または3番目のものを保存したい場合に使用します)を選択することです。 – nonegiven72
Railsでは生のSQLを使うのは簡単ですが、ActiveRecordはベビートークのSQLだけしか理解していないので、私はいつもやっています。 –