将含WHERE EXISTS的PostgreSQL查询转换为Django ORM
将PostgreSQL查询转换为Django ORM代码
原SQL逻辑分析
原查询的核心是获取每个group_uid和record_identifier分组下,id值最大的那条AuditHistory记录(通常id自增时,最大id对应分组内最新的操作记录)。
Django ORM实现代码
方法1:与原SQL逻辑完全匹配(使用Subquery)
from django.db.models import Subquery, OuterRef, Max # 构建子查询:获取每个(group_uid, record_identifier)分组的最大id max_history_subquery = AuditHistory.objects.filter( group_uid=OuterRef('group_uid'), record_identifier=OuterRef('record_identifier') ).values('group_uid', 'record_identifier').annotate( max_id=Max('id') ).values('max_id') # 主查询:筛选id属于对应分组最大id的记录 result = AuditHistory.objects.filter( id__in=Subquery(max_history_subquery) )
方法2:使用Window函数(更简洁高效)
如果你的Django版本在2.0及以上,可借助Window函数实现更直观的分组取最大逻辑:
from django.db.models import Window, Max from django.db.models.functions import RowNumber # 为每个分组内的记录按id降序添加行号,行号为1的就是最大id的记录 window = Window( partition_by=['group_uid', 'record_identifier'], order_by=('-id',) ) result = AuditHistory.objects.annotate( row_num=RowNumber().over(window) ).filter(row_num=1)
代码说明
- 方法1完全复刻原SQL的
EXISTS子查询逻辑,通过Subquery提取分组最大id集合,再用id__in筛选目标记录。 - 方法2利用Window函数为分组内的记录排序编号,直接取行号为1的记录,代码更简洁,多数场景下执行效率更优。
内容的提问来源于stack exchange,提问作者Anuj Singh
相关产品推荐
相关产品推荐

