4

我有一个数据库,其中包含 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 过滤器的原因之一——后者允许您简洁地说出您的意思。大概前者也可以表达查询,但我越来越对这种简单的解决方案感到绝望。

4

1 回答 1

1

您可以这样做 - 获取清单 1 的所有对象,并将其从完整列表中排除。

sku_ids = skus.values_list('pk', flat=True)
non_checklist_1 = SKU.objects.exclude(pk__in=sku_ids).distinct()
于 2012-09-30T03:14:05.020 回答