Django查询需求:按ID取最新创建对象并汇总字段+球队关联游戏取最新日期
Django查询需求解决方案
针对你提到的两个Django查询需求,我来一步步给你拆解实现方法:
需求1:查询每个ID对应的最新创建对象,并对其他字段求和
这个需求的核心是先锁定每个ID下最新创建的那条记录,再基于该ID进行字段求和(比如示例中的points)。这里我们用Subquery和聚合函数来实现:
假设你的模型结构如下(方便对应示例):
class Game(models.Model): id = models.IntegerField() # 这里指用户标识ID,若用Django默认主键可改为player_id等 first_name = models.CharField(max_length=100) last_name = models.CharField(max_length=100) date_created = models.DateTimeField() points = models.IntegerField() team = models.ForeignKey('Team', on_delete=models.CASCADE)
实现代码:
from django.db.models import Subquery, OuterRef, Max, Sum # 第一步:子查询获取每个ID对应的最新创建日期 latest_dates = Game.objects.filter(id=OuterRef('id')).values('id').annotate(latest_date=Max('date_created')).values('latest_date') # 第二步:筛选出每个ID的最新记录,同时对该ID的points字段求和 result = Game.objects.filter(date_created=Subquery(latest_dates)).values('id', 'first_name', 'last_name').annotate(total_points=Sum('points'))
代码说明:
- 子查询
latest_dates会为每个ID计算出最大的date_created值; - 主查询通过
date_created=Subquery(latest_dates)筛选出每个ID的最新记录; - 最后用
annotate(Sum('points'))对该ID下的所有points求和(如果需要仅对最新记录的points求和,去掉Sum直接取字段即可)。
需求2:获取特定Team关联的Games列表,仅保留每个记录的最后一个date_created日期
这个需求是要给指定Team下的每个用户ID,只保留其最新创建的Game记录。同样可以用Subquery或者Window函数实现:
方法一:Subquery方式(性能更优)
from django.db.models import Subquery, OuterRef, Max # 替换为你要查询的特定Team的ID target_team_id = 1 # 子查询获取该Team下每个ID的最新创建日期 latest_team_game_dates = Game.objects.filter( team_id=target_team_id, id=OuterRef('id') ).values('id').annotate(latest_date=Max('date_created')).values('latest_date') # 筛选出符合条件的最新记录 team_games = Game.objects.filter( team_id=target_team_id, date_created=Subquery(latest_team_game_dates) ).order_by('id')
方法二:Window函数方式(Django 3.2+支持)
如果你使用的是较新版本的Django,也可以用Window函数来标记每个ID的最新日期,再筛选:
from django.db.models import Window, Max, F target_team_id = 1 team_games = Game.objects.filter(team_id=target_team_id).annotate( # 给每条记录标记其所属ID的最新创建日期 latest_date=Window( expression=Max('date_created'), partition_by=['id'] # 按ID分组计算最新日期 ) ).filter(date_created=F('latest_date')) # 只保留创建日期等于最新日期的记录
效果说明:
针对你提供的示例数据,处理后id=3的记录只会保留date_created="2017-09-18T00:00:00"的那条,不会重复出现同一ID的多条旧记录。
内容的提问来源于stack exchange,提问作者kachus22
相关产品推荐
相关产品推荐

