我有一個數據庫,其中包含skus,套件,kit_contents和清單的模式。這裏是「一切爲包記錄定義kitcontent記錄中定義的單品在清單1中定義的給我」爲查詢:如何讓Django QuerySet'exclude'正常工作?
SELECT DISTINCT s.* FROM skus s
JOIN kit_contents kc ON kc.sku_id = s.id
JOIN kits k ON k.id = kc.kit_id
JOIN checklists c ON k.checklist_id = 1;
我使用Django的,我主要是很喜歡的ORM,因爲我可以表達通過查詢:
skus = SKU.objects.filter(kitcontent__kit__checklist_id=1).distinct()
這是這種瀏覽所有外鍵一個漂亮的方式。 Django的ORM產生與上面寫的SQL基本相同。問題在於,我不清楚如何獲得爲清單1定義的所有SKU 而不是。在上面的SQL查詢中,我將通過用「!=」替換「=」來做到這一點。但是Django的模型沒有一個不等於運算符。你應該使用排除()方法,其中一個可能已經猜到是這樣的:
skus = SKU.objects.filter().exclude(kitcontent__kit__checklist_id=1).distinct()
但Django的產生此查詢,這是不一樣的東西:
SELECT distinct s.* FROM skus s
WHERE NOT ((skus.id IN
(SELECT kc.sku_id FROM kit_contents kc
INNER JOIN kits k ON (kc.kit_id = k.id)
WHERE (k.checklist_id = 1 AND kc.sku_id IS NOT NULL))
AND skus.id IS NOT NULL))
(爲了便於閱讀和比較,我已經清理了查詢。)
我是Django ORM的初學者,我希望儘可能使用它。有沒有辦法在這裏得到我想要的東西?
編輯:
karthikr給了一個答案,不出於同樣的原因工作原ORM .exclude()解決方案不起作用:一個SKU可以在kit_contents在都存在套件checklist_id = 1和checklist_id = 2。使用通過手查詢我張開後與使用「checklist_id = 1」產生34分的結果,使用「checklist_id = 2」產生53分的結果,和下面的查詢產生26分的結果:
SELECT DISTINCT s.* FROM skus s
JOIN kit_contents kc ON kc.sku_id = s.id
JOIN kits k ON k.id = kc.kit_id
JOIN checklists c ON k.checklist_id = 1
JOIN kit_contents kc2 ON kc2.sku_id = s.id
JOIN kits k2 ON k2.id = kc2.kit_id
JOIN checklists c2 ON k2.checklist_id = 2;
我認爲這是人們似乎找不到.exclude()解決方案合理取代某種not_equals過濾器的原因之一 - 後者允許您簡潔地說出您的意思。據推測,前者也可以允許查詢表達,但我越來越絕望地認爲這種解決方案很簡單。
旁註:你不需要'過濾器的額外調用()',你可以做'SKU.objects.exclude(...)' – voithos
謝謝,好知道。 – shanusmagnus
是否要求所有與清單1無關的skus,或與清單1以外的清單相關的所有skus?或者「沒有爲清單1定義」意味着其他什麼? – dokkaebi