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

如何在Django中实现先取最大值再求和的嵌套聚合查询?

在Django中实现嵌套聚合查询(先取最大再求和)

问题分析

你尝试的第一种写法报错是因为Django不允许在同一个QuerySet中对聚合字段(如total)再次执行聚合操作,每次annotate与values的组合会重新触发分组,之前的聚合结果无法直接被后续聚合调用。

第二种子查询写法效率低下,是因为它生成了关联子查询(外层每行数据都会执行一次子查询),导致数据库执行成本指数级上升。

正确解决方案

我们可以分两步构建查询,让Django生成和你手写SQL结构一致的高效嵌套查询:

from django.db.models import Max, Sum

# 1. 先获取每个地点+类型的最大金额,同时关联对应的州信息
max_per_location_type = daily_data.objects.filter(
    type__in=['purchases', 'returns']
).values('location__state', 'location_id', 'type').annotate(
    max_amount=Max('amount')
)

# 2. 按州和类型分组,对每个州+类型下的所有地点最大金额求和
final_result = max_per_location_type.values('location__state', 'type').annotate(
    total_max_amount=Sum('max_amount')
).order_by('location__state', 'type')

生成的SQL说明

这段代码会生成与你手写SQL几乎完全一致的查询,先通过子查询一次性计算所有地点+类型的最大金额,再在外层做分组求和:

SELECT "locations"."state", "daily_data"."type", SUM("max_amount") AS "total_max_amount"
FROM (
    SELECT "locations"."state", "daily_data"."location_id", "daily_data"."type", MAX("daily_data"."amount") AS "max_amount"
    FROM "daily_data"
    INNER JOIN "locations" ON ("daily_data"."location_id" = "locations"."id")
    WHERE "daily_data"."type" IN ('purchases', 'returns')
    GROUP BY "locations"."state", "daily_data"."location_id", "daily_data"."type"
) AS "subquery"
GROUP BY "locations"."state", "daily_data"."type"
ORDER BY "locations"."state" ASC, "daily_data"."type" ASC

这种写法避免了关联子查询的性能问题,执行效率和你手写的原生SQL完全一致。

获取结果

遍历查询结果即可得到你预期的格式:

for item in final_result:
    print(f"{item['location__state']},{item['type']},{item['total_max_amount']}")

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 11:33:17