【问题标题】:Django ORM: how to make aggregation with filter with annotated field?Django ORM:如何使用带注释字段的过滤器进行聚合?
【发布时间】:2019-09-23 14:11:14
【问题描述】:

我有统计数据视图,我在某些基本查询集的不同过滤器上计算多个 count

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 时,一切都很好。

【问题讨论】:

  • 真正的过滤器是否包含__col2,最好看看是什么触发了错误,这样我们就可以看到什么导致了错误。
  • aggregation 是错字吗?应该是aggregate
  • 只要Count('pk', filter=Q(a__lt=5))。计算哪一列并不重要,但计算的列可能是个问题。
  • 我猜你想要的是一种“双重”注释。比如:qs.annotate(a=Count("a", filter=Q(a__lt=5)))
  • 我明白你的意思@dirkgroten。我误解了这个问题。所以,忽略我的评论:)

标签: django django-orm


【解决方案1】:

如果您使用的是 Django 2.2,您的方法应该有效,如 here 所述。您可能应该指望'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())
    )
)

【讨论】:

  • 我正在使用 django 2.0.3,Countfilter 通常工作,但如果我在 Count 的过滤器中使用注释字段,那么它会引发错误。与Sum(When) 相同。
  • 未知列错误?请更新您的问题以分享您的实际模型和查询集,以便我们重现您的问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-03-11
  • 2018-11-03
  • 2020-01-30
  • 2021-01-20
  • 2015-01-25
  • 2019-04-18
  • 2018-02-24
相关资源
最近更新 更多