gpt4 book ai didi

python - WHERE 子句中带有倒置 Q 对象的子查询

转载 作者:行者123 更新时间:2023-11-29 12:02:12 27 4
gpt4 key购买 nike

我有两个模型,其中一个引用另一个:

class A(models.Model):                                                          

variable = models.BooleanField(default=False, null=False)
b = models.ForeignKey(B, on_delete=models.CASCADE, related_name='as', related_query_name="a")


class B(models.Model):
pass

我想在过滤 variable 时追溯关系:

B.objects.filter(~Q(a__variable))

问题:这会在 where 子句中产生一个额外的子查询:

'SELECT "b"."id" FROM "b" WHERE NOT ("b"."id" IN (SELECT U1."b_id" FROM "a" U1 WHERE U1."variable" = True))'

另一方面,当不反转 Q 表达式时

B.objects.filter(Q(a__variable))

连接是“正确”完成的,即在 where 子句之外:

'SELECT "b"."id" FROM "b" INNER JOIN "a" ON ("b"."id" = "a"."b_id") WHERE "a"."variable" = True'

注意:我仅将 bool 值用作示例(我可以将其转换为 False)

我正在使用 django 2.0.4 和 postgres 9.6.2

最佳答案

简答:“所有 B 对象与相关 A 对象与 否定 variable = True不是查询“*所有 B 对象与相关 A 对象与 variable = False ”。

你可以这样查询:

B.objects.filter(a__variable=False)

或者如果该字段是NULL-able:

B.objects.filter(Q(a__variable=None) | Q(a__variable=False))

背景:否定存在量化表达式

这是预期的行为。因为如果您以一对多的方式查询相关模型,Django ORM 的设计者选择了存在量词∃而不是通用量词∀ 。没有固有的最佳选择,尽管我认为人类将执行的大多数查询都是存在量化*。

存在量词表示“存在”,因此如果您编写 B.objects.filter(a__variable=True),您会请求 B 对象,其中“存在一个具有variable=True的相关A对象。

但是 否定 不是 B 对象的列表“其中存在一个相关的 A 对象 variable=False”(让我们暂时忽略 NULL 花瓶)。实际上是一个 B 对象,它有两个相关的 A 对象,一个是 variable = True,一个是 variable = False 会在原始变体及其否定中出现

存在量化要求的否定是该谓词否定的普遍量化变体。或者在数学中:

¬∃x: P(x) ↔ ∀x: ¬ P(x)

因此这意味着查询“所有 B 对象存在 Avariable=True 的否定”,是查询“*所有 B 对象,所有 相关的 A 对象都有一个 变量 那是不是 B*”。注意第二个查询中的all。因此,这意味着对于 A 表中的每一行,我们需要“迭代”相关的“B”对象,以检查是否所有这些 variable 都是 正确。这并不是真正为 JOIN 量身定做的。对于 BooleanField,我们可以使用 GROUP BYMAX(..) 来做到这一点检查是否至少有一个这样的 TRUE 存在,从而限制它 TRUE。像这样的东西:

SELECT b.*, MAX(a.variable) AS mx
FROM b
LEFT OUTER JOIN b ON a.b_id = b.id
GROUP BY a.id
HAVING mx = FALSE OR mx IS NULL

但是这个“技巧”需要 Django ORM 查询构建器的一些“高级”tiling。这可能在未来的版本中最终得到支持,但无论如何,效率将大致相同。

关于python - WHERE 子句中带有倒置 Q 对象的子查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51983257/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com