You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Django查询构造器编写含Sum聚合字段的Case() SQL表达式

问题

需要用Django查询构造器重现以下SQL逻辑:

CASE
  WHEN sum(imps) = 0 THEN NULL
  ELSE SUM(total_expenses) / (sum(imps) / 1000)
END as "cpm"

尝试了以下代码,但运行报错TypeError: '>' not supported between instances of 'Sum' and 'int':

MyModel.objects.annotate(
  cpm=Case(
    When(
      Sum("imps")>0,
      then=Sum("total_expenses") / Sum("imps"),
    ),
    default=0,
    output_field=FloatField(),
 )
)

期望用类似total_imps__sum__gt=0的字段查询方式解决,不希望通过先注解total_imps=Sum("imps")再用total_imps__gt=0的冗余方式实现。

解决方案

可以用Django的Q()查询结合聚合筛选语法,直接在When的条件中判断聚合值,无需额外注解:

from django.db.models import Case, When, Sum, FloatField, Q

MyModel.objects.annotate(
    cpm=Case(
        When(
            Q(imps__sum__gt=0),
            then=Sum("total_expenses") / (Sum("imps") / 1000),
        ),
        default=None,  # 对应原SQL中的NULL逻辑
        output_field=FloatField(),
    )
)

关键说明:

  • Q(imps__sum__gt=0)是Django ORM支持的聚合筛选写法,能正确转换为SQL中的sum(imps) > 0条件,避免了直接用Sum("imps")>0引发的类型错误
  • 将default=0改为default=None,和原SQL的THEN NULL逻辑完全匹配
  • 还原原SQL的计算式SUM(total_expenses) / (sum(imps) / 1000),修正了原尝试代码中缺少除以1000的问题

这样就能在不创建多余注解的前提下,完美复现目标SQL的逻辑。

内容的提问来源于stack exchange,提问作者Cal El

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 20:40:56