如何在Django ORM中按用户分组统计月度总分并排名?
按用户分组统计月度总分并实现排名的解决方案
首先注意你的模型里quiz = models.ForeingKey(Quiz, on_delete=models.CASCADE)存在拼写错误,应改为ForeignKey,避免后续查询出现异常。
要实现按用户分组统计月度总分再排名,需先聚合用户的月度总分,再基于总分进行排名,具体实现代码如下:
from django.db.models import Sum, F from django.db.models.window import DenseRank from datetime import date # 过滤当月数据→按用户分组聚合总分→添加排名 user_monthly_rank = StudentAnswer.objects.filter( quiz__start_date__month=date.today().month, quiz__start_date__year=date.today().year # 新增年份过滤,避免跨年度同月数据干扰 ).values('user').annotate( total_marks=Sum('marks') # 累加每个用户的当月总分 ).annotate( rank=Window( expression=DenseRank(), order_by=F('total_marks').desc() # 按总分降序排名 ) ).order_by('rank') # 按排名排序输出结果
关键逻辑说明
values('user'):指定按user字段分组,确保每个用户仅返回一条聚合后的记录Sum('marks'):对每个用户当月所有StudentAnswer的marks字段求和,得到月度总分total_marksWindow(DenseRank()):基于聚合后的total_marks执行排名,DenseRank会让相同分数的用户获得相同排名,且排名不会出现断层(例如两个用户均得10分排第1,下一位用户直接排第2)- 新增年份过滤:避免统计往年同月的历史成绩,保证结果的准确性
如果需要同时获取用户的详细信息(如用户名),可调整values部分包含用户的关联字段:
.values('user', 'user__username').annotate( total_marks=Sum('marks') )...
内容的提问来源于stack exchange,提问作者Arthur Dayne
相关产品推荐
相关产品推荐

