Django 条件注释

Posted

技术标签:

【中文标题】Django 条件注释【英文标题】:Django conditional annotation 【发布时间】:2011-10-23 11:43:32 【问题描述】:

我很惊讶这个问题显然还不存在。如果有,请帮我找到它。

我想使用annotate(Count)和order_by,但我不想计算相关对象的每个实例,只计算满足某个标准的那些。

也就是说,我可以按照燕子携带的绿色椰子的数量来列出燕子:

swallow.objects.annotate(num_coconuts=Count('coconuts_carried__husk__color = "green"').order_by('num_coconuts')

【问题讨论】:

【参考方案1】:

对于 Django >= 1.8:

from django.db.models import Sum, Case, When, IntegerField

swallow.objects.annotate(
    num_coconuts=Sum(Case(
        When(coconuts_carried__husk__color="green", then=1),
        output_field=IntegerField(),
    ))
).order_by('num_coconuts')

【讨论】:

【参考方案2】:

这应该是正确的方法。

swallow.objects.filter(
    coconuts_carried__husk__color="green"
).annotate(
    num_coconuts=Count('coconuts_carried')
).order_by('num_coconuts')

请注意,当您过滤相关字段时,在原始 SQL 中,它会转换为 LEFT JOIN 加上 WHERE。最后,注释将作用于结果集,该结果集仅包含从第一个过滤器中选择的相关行。

【讨论】:

确实这似乎有效,但由于您指出的原因,这完全违反直觉。我希望这个查询集能给我所有曾经携带过至少一个绿色椰子的燕子,按携带的椰子总数排序,无论颜色如何。 @jMyles:文档指出这取决于order of the annotate and filter clauses - 反过来,它会按照您的描述运行。 如果你想把没有带任何绿色椰子的燕子包括在内怎么办? @tolomea 很多时间过去了,Django 可能同时发生了变化,但是 LEFT JOIN 保留了连接右侧部分为空的记录,并将列设置为 NULL。这应该转化为包括不携带绿色椰子的燕子。

以上是关于Django 条件注释的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Django 查询集中使用条件注释 Count

根据条件使用 ForeignKey Counts 注释 Django 查询集

将 DISTINCT 与多个条件聚合一起使用(注释)

Django 多注解返回错误结果

如何使用 StringAgg 或 ArrayAgg 连接多个子行中的一列来注释 django 查询集?

Django:基于注释进行注释