Django按Person分组查询每个人员最新拍摄日期的所有PersonPhoto照片
你当前的方案会先拉取全量人员的最大拍摄日期到Python层拼接查询条件,存在两次数据库查询,同时数据量大时内存占用也很高,以下是两种仅执行单次数据库查询的实现方案,所有逻辑都在数据库层完成:
方案1:窗口函数实现(兼容性最优,Django 2.0+ 支持)
该方案通过给同人员的照片按拍摄日期倒序排名,直接筛选出排名第一的所有照片,自动覆盖同一最新日期下的多张照片场景:
from django.db.models import F, Window from django.db.models.functions import Rank # 给每个人员的照片按拍摄日期倒序排名,最新日期的照片排名都是1 latest_photos = PersonPhoto.objects.annotate( date_rank = Window( expression = Rank(), partition_by = F('person_id'), order_by = F('date_captured').desc() ) ).filter(date_rank = 1).order_by('person_id') # 直接遍历结果即可 for photo in latest_photos: print(f"image for person {photo.person_id}, of date {photo.date_captured}")
方案2:子查询实现(Django 1.11+ 支持)
如果你的Django版本不支持窗口函数,可以用子查询实现,性能和窗口函数方案一致:
from django.db.models import Max, OuterRef, Subquery # 构造子查询:取对应人员的最大拍摄日期 latest_date_subq = PersonPhoto.objects.filter( person = OuterRef('person') ).values('person').annotate( max_date = Max('date_captured') ).values('max_date')[:1] # 直接过滤出日期等于对应人员最新日期的照片 latest_photos = PersonPhoto.objects.filter( date_captured = Subquery(latest_date_subq) ).order_by('person_id')
额外场景:仅需每人最新1张照片(PostgreSQL专属)
如果你用的是PostgreSQL数据库,且不需要同一最新日期的多张照片,只要每人最新的1张,可以用更简洁的distinct语法:
latest_photos = PersonPhoto.objects.order_by( 'person_id', '-date_captured' ).distinct('person_id')
内容的提问来源于stack exchange,提问作者user972014
相关产品推荐
相关产品推荐

