【问题标题】:Django Queryset returning different results for two exclude criteria and combined exclude criteriaDjango Queryset 为两个排除标准和组合排除标准返回不同的结果
【发布时间】:2020-09-25 02:33:59
【问题描述】:

为什么 django 会为以下两个排除语句返回不同的结果?

Django 排除语句 1:

self.fields.exclude(record_type__isnull=True, field=None).prefetch_related('field', 'field__table')

各自的 Django SQL 查询:

SELECT field1, field2, field__table FROM `table` WHERE (`table`.`t_ct_id` = 2 AND `table`.`t_id` = 32 AND NOT (`table`.`record_type` IS NULL AND `table`.`field_id` IS NULL))

记录数:395

Django 排除语句 2:

self.fields.exclude(record_type__isnull=True).exclude(field=None).prefetch_related('field', 'field__table')

各自的 Django SQL 查询 2:

SELECT field1, field2, field__table FROM `table` WHERE (`table`.`t_ct_id` = 2 AND `table`.`t_id` = 32 AND NOT (`table`.`incoming_record_type` IS NULL) AND NOT (`table`.`field_id` IS NULL))

记录数:152

我正在使用 django 版本 2.2.11 和 MYSQL 作为数据库

【问题讨论】:

  • 这是有道理的,因为对于两个排除标准,这意味着您排除了第一个和第二个元素。如果它在一个条件下,如果它与两个 combined 匹配,则排除记录。

标签: mysql django django-models django-rest-framework


【解决方案1】:

这是有道理的,因为对于两个排除条件,这意味着您排除了第一个和第二个的元素。如果它在一个条件下,如果它与两个组合匹配,则排除记录。

换句话说,在你说的第一个查询集中:

排除记录给定record_typeNULL 并且 fieldNULL。但如果两者中一个NULL(另一个不是),不要排除它。

在第二个查询集中,你说

排除record_typeNULL 的元素 fieldNULL(或两者均为NULL)。

因此,这意味着在第二个查询中,您排除了更多元素,即其中至少一个是NULL 的元素。如果您因此计算两者之一为NULL 的元素数,您将获得 243 条记录:

# will return 243 records where exactly one of the two fields is NULL

from django.db.models import Q

self.fields.filter(
    Q(record_type__isnull=False, field__isnull=True) |
    Q(record_type__isnull=True, field__isnull=False)
).count()  # 243

但是,您可以在单个排除语句中编写两个排除的逻辑:

# 152 records

from django.db.models import Q

self.fields.exclude(
    Q(record_type=None) | Q(field=None)
).prefetch_related('field', 'field__table')

因此,我们从两个字段之一为NULL(或两者)的那一刻开始排除记录。

Exclude 因此过滤条件的否定。由于De Morgan's laws [wiki] 状态,¬(A &wedge; B) = ¬A&vee;¬B,所以NOT (<i>a</i> AND <i>b</i>)NOT <i>a</i> <b>OR</b> NOT <i>b</i> 相同。

【讨论】:

  • 即使底层 SQL 查询位于 AND 中,它仍将充当 OR
  • @slash:(x and y)的否定是(not x or not y),即De Morgan's laws。这与 MySQL、SQL 或编程无关,而是(布尔)逻辑。
  • 我只实现了Q(record_type=None) | Q(field=None),它起作用了,但我很困惑为什么它在上述两种情况下不起作用。
  • 现在我明白了。谢谢。
猜你喜欢
  • 1970-01-01
  • 2023-04-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-06-18
  • 1970-01-01
  • 2018-02-13
  • 2012-04-28
相关资源
最近更新 更多