我有一个数据库,其中包含 skus、kits、kit_contents 和清单的模式。这是一个查询“给我为清单 1 中定义的套件记录定义的套件内容记录定义的所有 SKU”:
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 的模型没有不等于运算符。你应该使用 exclude() 方法,有人可能会猜到它看起来像这样:
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 可以在checklist_id=1 和 checklist_id=2上都存在的套件中的 kit_contents 中。使用我打开帖子时使用的手动查询,使用“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 过滤器的原因之一——后者允许您简洁地说出您的意思。大概前者也可以表达查询,但我越来越对这种简单的解决方案感到绝望。