如何在Django中基于日期与时间执行聚合查询操作?
Django 基于日期/时间维度的聚合统计实践
刚好之前也处理过类似的Django聚合需求,结合你给出的Something模型,我整理了几种实用的日期、时间维度统计方法,咱们一步步来看:
首先再明确下演示用的模型结构:
class Something(models.Model): date = models.DateField() time = models.TimeField() timestamp = models.DateTimeField() price = models.DecimalField() manufacturer = models.CharField()
你提到的统计每个厂商的记录总数,代码可以这么写(注意Count里要指定具体字段,比如id或者用*,避免因为字段为空导致统计不准):
from django.db.models import Count # 统计每个厂商的记录总数 Something.objects.all().values("manufacturer").annotate(frequency=Count('id'))
接下来重点说基于日期、时间的聚合操作,分几种常见场景:
1. 按日期(天)维度统计
不管是用模型里单独的date字段,还是从timestamp字段中提取日期,都能实现按天统计:
- 直接用
date字段统计:
from django.db.models import Count, Avg # 统计每天的记录总数 Something.objects.values("date").annotate(daily_total=Count('id')) # 统计每天的平均商品价格 Something.objects.values("date").annotate(daily_avg_price=Avg('price'))
- 从
DateTimeField中提取日期(适合只有timestamp没有单独date字段的场景):
from django.db.models.functions import TruncDate # 从timestamp字段提取日期维度,统计每天的记录数 Something.objects.annotate(day=TruncDate('timestamp')).values("day").annotate(daily_total=Count('id'))
2. 按时间(小时/分钟)维度统计
如果要分析一天中不同时间段的业务数据,比如每个小时的订单量,可以这么做:
- 用单独的
time字段提取小时:
from django.db.models.functions import ExtractHour # 统计一天中每个小时的记录数 Something.objects.annotate(hour=ExtractHour('time')).values("hour").annotate(hourly_total=Count('id'))
- 从
timestamp字段提取小时,同时统计销售额:
from django.db.models import Sum # 按小时统计总销售额 Something.objects.annotate(hour=ExtractHour('timestamp')).values("hour").annotate(hourly_sales=Sum('price'))
3. 按日期+时间组合维度统计
如果需要更精细的粒度,比如统计每天每个小时的记录数,可以组合日期和小时两个维度:
# 按日期+小时的组合维度统计,并且按时间排序 Something.objects.annotate( day=TruncDate('timestamp'), hour=ExtractHour('timestamp') ).values("day", "hour").annotate(total=Count('id')).order_by("day", "hour")
4. 按周/月/季度等大时间维度统计
如果需要做周期性的统计,比如月度销售报表,可以用TruncWeek、TruncMonth这类函数:
from django.db.models.functions import TruncMonth # 按月份统计每月的总销售额 Something.objects.annotate(month=TruncMonth('timestamp')).values("month").annotate(monthly_sales=Sum('price'))
内容的提问来源于stack exchange,提问作者IordanouGiannis
相关产品推荐
相关产品推荐

