2012-03-21 48 views
1

我幾次見過這個問題,但所有的答案都依賴於小數據集或有限的關聯,所以這裏再次提到。查找不在連接中的記錄 - 高效地

我有一個has_many_through關係

class ModelA 
    has_many :model_c, :through => :model_b 
    has_many :model_b 

class ModelB 
    belongs_to :model_a 
    belongs_to :model_b 

class ModelC 
    has_many :model_a, :through => :model_b 
    has_many :model_b 

我需要清理「孤兒」模型B的和C型的 - 其中A型車已被刪除。因此,我需要找到並刪除模型B的沒有模型A,然後刪除模型C的沒有模型B.

我們沒有這樣做時刪除模型A的因爲一個模型A可以關聯到成千上萬的模型C的時間太長了 - 我們使用帶有防護塊的依賴銷燬方式引發了太多的查詢並花了太長時間。我們打算現在做一個每晚清理工作。

因此,我需要找到並刪除所有ModelB的model_a列包含一個現在不存在的Model A的ID,並刪除它們。

我迄今發現的解決方案不適用於我(因爲我們在給定時間可能會有成千上萬的孤​​兒): - 從ModelA.id和ModelB.model_a加載所有ID並執行設定的差 - 從ModelA.id加載所有的識別碼與傳遞到「NOT IN」查詢對B型 - 從C型記錄被記錄

檢查在這一點上,我想我需要一個直SQL解決方案(我很好),但我不太確定我在找什麼。

(DB是MySQL的)

+0

如果你想要一個SQL解決方案,請重新改寫在SQL你的問題,這將工作。對於一些(大多數)大師,恕我直言,你提供的速記符號是不可讀的。 – wildplasser 2012-03-21 20:10:25

回答

3

我沒有測試過,但我相信,如果理解MySQL Multiple-table Delete Syntax

DELETE 
    ModelC, 
     ModelB 
FROM ModelC 
    LEFT JOIN ModelB 
    ON ModelC.BID = ModelB.BID 
    LEFT JOIN ModelA 
    ON ModelB.AID = ModelA.AID 
WHERE 
    ModelB.BID is NULL 
    OR ModelA.AID IS NULL 
+0

+1'LEFT JOIN'並檢查null是找到缺失條目的典型SQL方法。 – 2012-03-21 20:19:39

+0

謝謝。嘗試一下。將確認一旦它的工作。 – 2012-03-22 00:22:01

+0

所以,這是最正確的,但爲了得到我需要的效果,我必須做2個查詢 - 首先刪除模型B,然後刪除模型C.否則,模型C的孤立模型B,但也是好模型B的,將被刪除。我們希望保留模型C,如果他們至少有一個到模型A的有效連接。這讓我走了,但是,謝謝。 – 2012-03-22 01:45:32