どういうスキーマなのかよく分からなかったので、customers
を以下として考えています。
rb
1create_table "customers", force: :cascade do |t|
2 t.string "industry", null: false
3 t.datetime "created_at", null: false
4 t.datetime "updated_at", null: false
5 end
ワンライナーで出来るかな?と考えてみましたが、複雑すぎたので諦めました。ActiveRecordらしく(Rubyらしく?)書くと、こんな感じでしょうか。
ruby
1ActiveRecord::Base.transaction do
2 Customer.group(:industry).having('COUNT(industry) >= 2').pluck(:industry).each do |industry|
3 max_val = Customer.where(industry: industry).maximum(:created_at)
4 Customer.where(industry: industry).where('created_at < ?', max_val).destroy_all
5 end
6end
重複しているindustry
の一覧を元にeach
でループ処理を行い、それぞれのindustry
の最新の日付情報を取得して、それ以前のデータを全て削除しています。もっと良い集計方法があればいいのですが。普通にN+1問題
となってしまいます。
一応、相関サブクエリを使った方法も考えてみたのですが、ActiveRecordで表現するのが厳しかったです。動作確認が出来たSQLだけ貼っておきますのでご参考までに。
sql
1DELETE FROM customers WHERE id IN (
2 SELECT
3 id
4 FROM
5 (
6 SELECT * FROM customers AS C1 WHERE C1.industry IN (SELECT industry FROM customers GROUP BY industry HAVING COUNT(industry) >= 2)
7 ) AS C2
8 WHERE
9 C2.created_at < (
10 SELECT MAX(created_at) FROM customers AS C3 WHERE C3.industry = C2.industry
11 )
12);