如何在Django中按非唯一字段获取指定sku的最新去重记录?
解决Django中获取每个SKU最新描述的问题
问题背景
给定模型:
class Item(models.Model): sku = models.CharField(null=False) description = models.CharField(null=True)
需要从指定SKU列表中,获取每个SKU对应**id最大(最新)**记录的描述。
原写法的问题
你之前的代码中Latest聚合的调用方式有误,正确的Latest需要明确指定排序字段作为参数,而非在后面链式调用order_by,且这种方式在处理可空字段时可能存在异常,因此更推荐以下两种可靠方案。
方案一:子查询获取最大ID关联查询
通过子查询先拿到每个SKU的最大ID,再关联到对应的记录:
from django.db.models import OuterRef, Subquery, Max # 子查询:获取每个sku的最大id max_id_subquery = Item.objects.filter(sku=OuterRef('sku')).values('sku').annotate(max_id=Max('id')).values('max_id') # 过滤出所有sku在目标列表中,且id为对应sku最大id的记录 latest_items = Item.objects.filter( id__in=Subquery(max_id_subquery), sku__in=list_of_skus ) # 转换为sku到描述的字典,方便使用 sku_latest_descr = {item.sku: item.description for item in latest_items}
方案二:使用Window函数排名筛选
利用Window函数给每个SKU的记录按id倒序排名,取排名第一的记录:
from django.db.models import Window, F from django.db.models.functions import Rank # 给每个sku的记录按id降序排名 ranked_items = Item.objects.filter(sku__in=list_of_skus).annotate( rank=Window( expression=Rank(), partition_by=F('sku'), order_by=F('id').desc() ) ).filter(rank=1) # 转换为sku到描述的字典 sku_latest_descr = {item.sku: item.description for item in ranked_items}
补充说明
如果一定要使用Latest聚合,正确的写法应该是:
from django.db.models import Latest latest_skus = Item.objects.values('sku').filter(sku__in=list_of_skus).annotate( latest_descr=Latest('description', order_by='-id') ).values('sku', 'latest_descr')
但这种方式在description存在空值时,可能无法正确返回预期结果,因此更推荐前两种方案。
内容的提问来源于stack exchange,提问作者dekomote
相关产品推荐
相关产品推荐

