Django ORM使用distinct去重时按created_at排序失效的解决方法咨询
问题根因
你当前的写法仅针对PostgreSQL数据库有效,逻辑是按lead_id分组去重时,每个lead_id保留created_at最新的一条记录,但最终返回结果的排序规则是优先按lead_id升序排序,同lead_id下才按created_at降序排序,不会全局按created_at排序,这就是你感觉排序逻辑不生效的核心原因。
替代解决方案
方案1:子查询二次查询(全数据库兼容)
先拿到去重后的记录ID集合,再对目标结果做全局排序:
# 第一步:查询每个lead_id对应最新记录的主键ID distinct_record_ids = IncomingCallRecording.objects.order_by("lead_id", "-created_at").distinct("lead_id").values_list("id", flat=True) # 第二步:过滤出目标记录后按created_at全局排序 sorted_result = IncomingCallRecording.objects.filter(id__in=distinct_record_ids).order_by("-created_at")
该方案兼容MySQL、PostgreSQL等所有Django支持的数据库,代码逻辑简单易维护。
方案2:窗口函数实现(单查询完成,PostgreSQL/MySQL 8.0+支持)
通过RowNumber窗口函数标记每个lead_id分组下的记录排序,过滤出第一条后直接全局排序:
from django.db.models import Window, F from django.db.models.functions import RowNumber sorted_result = IncomingCallRecording.objects.annotate( # 按lead_id分组,组内按created_at倒序编号 row_num=Window( expression=RowNumber(), partition_by=F('lead_id'), order_by=F('created_at').desc() ) ).filter(row_num=1).order_by('-created_at')
该方案仅需一次数据库查询,适合数据量较大、需要拼接复杂查询逻辑的场景。
内容的提问来源于stack exchange,提问作者Sidhar_t.py
相关产品推荐
相关产品推荐

