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

Django QuerySet如何基于Avg聚合条件按月统计A模型实例数量

问题原因

原有ORM代码存在两个核心错误:

  • 语法错误:amountfield__avg是聚合运算后缀,不能直接写在Q()对象中作为过滤条件,只有提前通过annotate定义聚合字段后,才能在过滤逻辑里引用聚合结果
  • 逻辑错误:直接按月份单维度分组,会把同一个月下所有不同A实例关联的B记录混在一起计算,无法单独判断每个A实例的关联B平均值是否为0,分组维度不符合需求

额外注意:直接取datetimefield__month会把不同年份的同月份数据合并(比如2023年1月和2024年1月会被算成同一个月),统计结果不符合绝大多数按月统计的业务要求,建议用TruncMonth做时间截断保留年月维度。

正确实现代码

首先导入需要的依赖:

from django.db.models import Avg, Count
from django.db.models.functions import TruncMonth

分两次分组实现统计需求:

stat_result = (
    B.objects
    # 截断时间到年月维度
    .annotate(month=TruncMonth("datetimefield"))
    # 第一级分组:按 月份 + 关联的A实例 分组,计算每个A在对应月份的amount平均值
    .values("month", "a_field")
    .annotate(avg_amount=Avg("amountfield"))
    # 过滤出平均值为0的A+月份组合
    .filter(avg_amount=0)
    # 第二级分组:按月份分组,统计每个月符合条件的A实例数量
    .values("month")
    .annotate(valid_a_count=Count("a_field", distinct=True))
    .order_by("month")
)
结果说明

返回的查询集中每个元素包含两个字段:

  • month:对应统计的年月(datetime类型,比如2024-01-01表示2024年1月)
  • valid_a_count:该月份下,关联B记录的amountfield平均值为0的A实例数量

如果你确实不需要区分年份,只需要按1-12的自然月统计,可以把TruncMonth("datetimefield")替换为datetimefield__month,后续分组字段对应改成datetimefield__month即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 00:18:20