Python中如何在Django框架下进行分组统计?
model 结构是 id,add_date,car_id,service_item car_id 是外键。
Service.objects.annotate(car_count=Count('car_id')) 想按 car_id 进行分组统计,但结果是一条记录一行。似乎是受日期字段的影响。 纯 sql 好解决,在 model 的范围内,怎么处理?
Python中如何在Django框架下进行分组统计?
如果是想统计每个 car_id 有多少个 service, 即按照 car_id 进行 group by
那么 Service.objects.values(‘car_id’).annotate(car_count=Count(‘car_id’)) 即可
你可以在每条 queryset 后面, 用.query 看对应 queryset 的 sql 语句
Service.objects.values(‘car_id’).annotate(car_count=Count(‘car_id’)).query
大致就是 select car_id, count(‘car_id’) from service group by car_id.
在Django里做分组统计,用ORM的annotate()和values()配合起来最直接。比如你要按category分组统计文章数量,可以这么写:
from django.db.models import Count
from myapp.models import Article
# 基础分组统计:按category字段分组,并统计每组的数量
result = Article.objects.values('category').annotate(total=Count('id')).order_by('category')
# 结果是一个QuerySet,每个元素是字典
for item in result:
print(f"Category: {item['category']}, Count: {item['total']}")
如果你需要更复杂的条件,比如只统计已发布的文章,可以加filter():
result = Article.objects.filter(status='published').values('category').annotate(total=Count('id'))
要同时统计多个聚合值,比如每组的文章数和总阅读量:
from django.db.models import Sum
result = Article.objects.values('category').annotate(
article_count=Count('id'),
total_views=Sum('views')
)
对于多对多关系的分组统计(比如按标签统计文章),思路类似,但要注意通过关系字段查询:
# 假设Article模型有tags多对多字段
result = Article.objects.values('tags__name').annotate(count=Count('id')).filter(tags__isnull=False)
关键就两点:values()指定分组字段,annotate()添加聚合统计。这样生成的SQL效率高,而且完全利用Django ORM的优势,不用写原生SQL。
总结:用values().annotate()组合搞定分组统计。
这样的结果是正确的,只是未能选出其它字段,如 service_item 和 add_date,如何同时选出统计结果和其它字段?
values 中一旦添加其它字段,统计结果就为 1,完全没分组。
model 感觉不如 sql 来的直接。
分组聚类计算用 annotate,如果你的 model.META 里定义了 ordering 属性,需要在 annotate 之后 order_by()一下。
应该就不会出现你说的聚类受日期影响了
car_id 和 service 是一对多的关系, 所以你取出来的时候, 到底取哪个 add_date 呢?
values 里的字段, 在这里是 group by 里的字段.
group by 多个字段, 自然数量大多是 1 了.
是否是说,不能同时取出表内其它字段和统计结果,只能取到聚合字段和统计值?
先取出字段信息,再计算统计结果,如何进行关联并显示呢?
“纯 sql 好解决”,“ model 感觉不如 sql 来的直接”,你想要的 SQL 怎么写的?
1 .用物化(索引)视图实现,模型绑定视图。
2. 通过模型获取需要的数据,应用内分组汇总。
楼主注意,annotate 有个坑
如果你的 Model 定义了默认排序字段, 必须要加 order_by()
Service.objects.values(‘car_id’).annotate(car_count=Count(‘car_id’)).order_by()
这个不是 django 的 order by 的坑,而是数据库的坑。如果数据库遵守 sql 标准的话就存在这个所谓的“坑”(其实不是坑,而是标准),如果是 mysql 的话就会放你一马
谢谢楼上二位,问题是我没在 model 中加 order_by,稍后再研究下 annotate。
现在在 model 定义了函数,返回 count。每一行一个二次查询。不雅,总算能解决问题。
跨表统计这种情况,还是要小心研究下,以后只会多不会少。mongodb 中似乎也不方便。还是老老实实 mysql 吧。
#11 lz 我也遇到同样的问题了,除了二段查询有别的解决方法吗

