Sql 如何获得Django QuerySet';排除';工作正常吗?
我有一个数据库,其中包含SKU、套件、套件内容和检查表的模式。这里是一个查询“给我为清单1中定义的套件记录定义的kitcontent记录定义的所有SKU”: 我使用的是Django,我非常喜欢ORM,因为我可以通过以下方式表达该查询:Sql 如何获得Django QuerySet';排除';工作正常吗?,sql,django,orm,Sql,Django,Orm,我有一个数据库,其中包含SKU、套件、套件内容和检查表的模式。这里是一个查询“给我为清单1中定义的套件记录定义的kitcontent记录定义的所有SKU”: 我使用的是Django,我非常喜欢ORM,因为我可以通过以下方式表达该查询: skus = SKU.objects.filter(kitcontent__kit__checklist_id=1).distinct() 这是一个如此巧妙的方式来导航所有这些外键。Django的ORM生成的SQL与上面编写的SQL基本相同。问题是我不清楚如何获
skus = SKU.objects.filter(kitcontent__kit__checklist_id=1).distinct()
这是一个如此巧妙的方式来导航所有这些外键。Django的ORM生成的SQL与上面编写的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_内容中。使用我打开帖子时使用的手动查询,使用“checklist\u id=1”生成34个结果,使用“checklist\u 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()解决方案是某种非_equals过滤器的合理替代品的一个原因——后者允许您简明扼要地说出您的确切意思。想必前者也允许表达查询,但我越来越不希望这样的解决方案简单。您可以这样做-获取清单1的所有对象,并将其从完整列表中排除
sku_ids = skus.values_list('pk', flat=True)
non_checklist_1 = SKU.objects.exclude(pk__in=sku_ids).distinct()
旁注:您不需要额外调用
filter()
,只需执行SKU.objects.exclude(…)
是否希望所有与清单1无关的SKU,或与清单1以外的SKU相关?或者“清单1未定义”完全是指其他内容吗?与清单1以外的清单相关的所有SKU。困难似乎在于它们可能也与1有关,但我不想知道它们与1有关的意义。我最初的SQL查询中的连接语法表达了这种区别(废话废话连接检查表c,其中k.checklists.id!=1),但我无法排除。请这样做。谢谢您的回答;但请查看我的编辑,了解为什么它不起作用。
sku_ids = skus.values_list('pk', flat=True)
non_checklist_1 = SKU.objects.exclude(pk__in=sku_ids).distinct()