首页 > 解决方案 > Django ORM:如何使用带注释字段的过滤器进行聚合?

问题描述

我查看了统计信息,其中我计算count了一些基本查询集的不同过滤器上的多个 's:

qs = Model.onjects.filter(...).annotate(a=...)
a = qs.filter(Q(a__lt=5)).count()
b = qs.filter(Q(a__lt=10)).count()  # this is just an example, real filters are more complex
...

但是每个计数都会对数据库进行单独的查询,我想对其进行优化。我试过aggregation

qs.aggregate(
  a=Count('a', filter=Q(a__lt=5)), 
  b=Count('a', filter=Q(a__lt=10)),
)

但有一个错误:django.db.utils.OperationalError: (1054, "Unknown column '__col2' in 'field list'")。我什至不知道这__col2是从哪里来的。

似乎聚合不适用于注释,因为当我在内部使用常规模型字段count.filter而不是注释字段时,a一切都很好。

标签: djangodjango-orm

解决方案


如果您使用的是 Django 2.2,那么您的方法应该有效,如此所述。你可能应该指望'pk'那里显示,不确定你可以指望注释本身:

qs.aggregate(
    a=Count('pk', filter(Q(a__lt=5)),
    b=Count('pk', filter(Q(a__lt=10))
)

如果您使用的是 Django 1.11,则上述方法不起作用,因为Count将始终返回 1,忽略过滤器。你应该使用Case ... When

qs.aggregate(
    a=Sum(
        Case(When(a__lt=5, then=1),
             output_field=IntegerField())
    ),
    b=Sum(
        Case(When(a__lt=10, then=1),
             output_field=IntegerField())
    )
)

推荐阅读