したいこと
子テーブルから、親テーブルのレコードが存在しないものを削除する。
plan belongs_to :user
user has_many :plans
という一対多の関係。
SQL
SELECT
1
2
3
4
5
|
SELECT *
FROM plans
LEFT JOIN users
ON (plans.user_id = users.id)
WHERE users.id IS NULL
|
DELETE
以下の書き方の場合はエラーが出る。
1
2
3
4
5
6
7
8
|
DELETE
FROM plans
WHERE plans.id
IN (SELECT plans.id
FROM plans
LEFT JOIN users
ON (plans.user_id = users.id)
WHERE users.id IS NULL)
|
You can’t specify target table ‘***’ for update in FROM clause〜MySQLにて、サブクエリのみに適用されるエラーがある〜 - 君は心理学者なのか?
plans.id
が重複しているので、SELECTで取得したカラムに仮の名前(tmp)を付けてあげる。
1
2
3
4
5
6
7
8
9
|
DELETE FROM plans
WHERE plans.id
IN (SELECT tmp.id
FROM (SELECT plans.id
FROM plans
LEFT JOIN users
ON (plans.user_id = users.id)
WHERE users.id IS NULL)
AS tmp)
|
ActiveRecord
親を持たない子レコードを取得する。
1
|
Plan.left_joins(:user).where(users: { id: nil })
|
joins
はPlanからの関連なので単数形、where
はテーブル名なので複数形。