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

不使用Raw SQL,如何用Django Query合并两张分组统计结果表

解决方案:合并Django分组统计结果并显示双列计数

方案一:单查询实现双条件计数(推荐)

直接在数据库层面完成统计,用Case和When区分不同条件的计数,一次查询搞定,效率最高:

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

# 统计每个name在两个条件下的计数,无数据则显示0
result = Entity.objects.filter(some_condition__in=[1, 2])
    .values("name")
    .annotate(
        count_condition1=Count(Case(
            When(some_condition=1, then=1),
            output_field=IntegerField()
        )),
        count_condition2=Count(Case(
            When(some_condition=2, then=1),
            output_field=IntegerField()
        ))
    )

返回的每条结果包含name、count_condition1(对应原q1的计数)、count_condition2(对应原q2的计数)三个字段,自动处理无数据的情况为0。如果要包含所有name(哪怕两个条件下都没数据),删掉filter(some_condition__in=[1, 2])即可。

方案二:内存合并已有查询集

如果已经生成了q1和q2,可转成字典后合并:

# 将查询集转为{name: 计数}的字典
dict_q1 = {item["name"]: item["name__count"] for item in q1}
dict_q2 = {item["name"]: item["name__count"] for item in q2}

# 提取所有出现过的name
all_names = set(dict_q1.keys()).union(set(dict_q2.keys()))

# 生成合并后的结果列表
merged_result = [
    {
        "name": name,
        "count_condition1": dict_q1.get(name, 0),
        "count_condition2": dict_q2.get(name, 0)
    }
    for name in all_names
]

这种方式会触发两次数据库查询,适合数据量较小的场景。

为什么之前的方法失效?

  • q1 | q2会把两个查询的结果合并,Django会自动将同name的计数合并到同一列,无法区分是哪个条件的统计结果。
  • union要求两个查询集的字段完全一致,且annotate生成的查询默认带排序,而SQL的复合查询不允许子查询包含ORDER BY,所以报错。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 09:07:47