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

能否通过单条Django查询获取指定人员分月销售总额?

问题解答

需求明确

需按月份统计John和Mary的销售总额(求和),忽略其他销售人员的数据;日期以「年份-月份」格式按时间从旧到新排序,哪怕某人员在对应月份没有销售额(总额为0),也要显示该记录。

给定信息

示例输出数据:

[
  ["19-Nov", "John", 511.97], ["19-Nov", "Mary", 0], 
  ["19-Dec", "John", 568.21], ["19-Dec", "Mary", 1542.08], 
  ["20-Jan", "John", 621.20], ["20-Jan", "Mary", 401.06], 
  ["20-Feb", "John", 621.39], ["20-Feb", "Mary", 0], 
  ["20-Mar", "John", 0], ["20-Mar", "Mary", 871.14], 
  ["20-Apr", "John", 604.25], ["20-Apr", "Mary", 653.34], 
  ["20-May", "John", 584.94], ["20-May", "Mary", 1218.43],
]

Django模型定义:

class Sellers(models.Model):
    date = models.DateField()
    name = models.CharField(max_length=300)
    value = models.DecimalField(max_digits=19, decimal_places=2)

核心答案

完全可以用单条Django查询搭配聚合、条件表达式实现需求,但要注意:必须先确定要统计的完整月份范围——因为要显示0销售额的记录,哪怕某月份里John或Mary没有对应数据。

实现步骤与代码

  1. 先拿到所有需要统计的月份:从数据库中提取所有涉及的月份(或者指定固定范围),确保没有遗漏。
  2. 单条查询完成分组与条件求和:按月份分组,分别计算John和Mary的销售额,无数据时返回0。
  3. 转换为目标格式:把查询结果拆分成示例要求的二维数组结构。
from django.db.models import Sum, Case, When, Value, DecimalField
from django.db.models.functions import TruncMonth

# 1. 获取数据库中所有涉及的月份(按时间升序)
all_target_months = Sellers.objects.dates('date', 'month', order='ASC')

# 2. 核心查询:按月份分组,统计John和Mary的销售额(无数据则为0)
monthly_totals = Sellers.objects.filter(name__in=['John', 'Mary']) \
    .annotate(month=TruncMonth('date')) \
    .values('month') \
    .annotate(
        john_sum=Sum(
            Case(When(name='John', then='value'), default=Value(0), output_field=DecimalField())
        ),
        mary_sum=Sum(
            Case(When(name='Mary', then='value'), default=Value(0), output_field=DecimalField())
        )
    ) \
    .order_by('month')

# 3. 转换为示例要求的格式
result = []
# 把查询结果转成字典,方便快速查找对应月份的数据
month_dict = {item['month']: item for item in monthly_totals}

for month in all_target_months:
    # 格式化月份为「年份-月份」格式(如"19-Nov")
    month_str = month.strftime("%y-%b")
    # 取对应数据,无则为0
    john_val = month_dict.get(month, {}).get('john_sum', 0)
    mary_val = month_dict.get(month, {}).get('mary_sum', 0)
    # 添加到结果数组
    result.append([month_str, 'John', john_val])
    result.append([month_str, 'Mary', mary_val])

关键细节说明

  • TruncMonth:Django内置的日期函数,把date字段截断到月份级别,用来实现按月份分组。
  • Case/When + Sum:精准筛选对应人员的销售额求和,没有数据时用default=Value(0)返回0,满足“即使销售额为0也需显示”的要求。
  • 遍历所有目标月份:确保每个月份都能生成John和Mary的记录,不会因为某人员当月无数据就漏掉条目。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 22:27:19