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

如何统计Django中每日成本超当日均值的采购订单数量?

Django统计每日成本超平均的采购订单数问题解决

问题分析

你原代码的错误在于:在同一个values('date')后的链式annotate中,第二个annotate里的Sum(Case(...))尝试直接引用第一个annotate生成的聚合字段avg_cost,但Django ORM不允许在聚合函数内部的条件判断中直接引用同层级的聚合结果——因为分组聚合是对整组数据计算的,行级的cost无法在聚合阶段直接和组级的avg_cost做比较。

可行解决方案

你的需求完全可以实现,以下是两种可靠的写法:

方法1:子查询+分组计数

先通过子查询获取每个日期的平均成本,再过滤出成本超标的记录并分组统计:

from django.db.models import Avg, Count, Subquery, OuterRef

# 子查询:计算每个日期的平均采购成本
daily_avg_subquery = Purchase.objects.filter(
    date=OuterRef('date')
).values('date').annotate(avg_cost=Avg('cost')).values('avg_cost')

# 主查询:过滤出成本超过当日平均的记录,按日期分组统计数量
result = Purchase.objects.filter(
    cost__gt=Subquery(daily_avg_subquery)
).values('date').annotate(purchases_above=Count('id'))

方法2:Window函数+过滤分组

利用Window函数为每条记录标记其所属日期的平均成本,再过滤统计:

from django.db.models import Avg, Count, Window, F

# 为每条记录添加当日平均成本字段
purchase_with_daily_avg = Purchase.objects.annotate(
    daily_avg=Window(
        expression=Avg('cost'),
        partition_by=['date'],  # 按日期分组计算平均
        frame=RowRange(start=None, end=None)  # 包含整组所有记录
    )
)

# 过滤出成本超标的记录,按日期分组计数
result = purchase_with_daily_avg.filter(
    cost__gt=F('daily_avg')
).values('date').annotate(purchases_above=Count('id'))

结果说明

两种方法最终都会返回一个QuerySet,每个元素是类似{'date': datetime.date(2024, 1, 1), 'purchases_above': 3}的字典,代表对应日期有3笔采购订单成本超过当日平均。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 14:32:06