SQLAlchemy筛选仅保留最新记录 子查询group_by报错解决
问题背景
需要实现和下述原生SQL逻辑完全等价的SQLAlchemy查询,目标是关联events表和event_types表时,仅保留每个event_type对应created_at最新的event_types记录,最终返回events表全量字段:
SELECT * FROM events AS ev INNER JOIN event_types AS et1 on ev.event_type_id = et1.id INNER JOIN ( SELECT event_type, MAX(created_at) AS LatestCreatedAt FROM event_types et GROUP BY event_type ) AS et2 ON et2.event_type = et1.event_type AND et2.LatestCreatedAt = et1.created_at
原有实现代码抛出Neither 'max' object nor 'Comparator' object has an attribute 'group_by'报错,无法正常运行。
错误原因
原有代码存在三处核心问题:
group_by是ORM查询对象的方法,不属于func.max()生成的聚合函数表达式,把group_by链式调用在func.max()后面属于调用位置错误- 构建子查询时直接调用了
.all(),会立刻执行SQL将结果加载为Python内存列表,无法作为SQL层面的虚拟表参与后续join关联 - 关联子查询时没有显式指定连接条件,子查询和实体表不存在默认外键关联,会导致SQLAlchemy无法生成正确的关联逻辑
正确实现代码
from sqlalchemy import func # 构建对应et2的分组聚合子查询 et2_subquery = session.query( EventTypeTable.event_type, func.max(EventTypeTable.created_at).label("LatestCreatedAt") ).group_by(EventTypeTable.event_type).subquery(name="et2") # 构建主查询 events = ( session.query(EventTable) # 关联et1:event_types主表,显式指定外键关联条件 .join(EventTypeTable, EventTable.event_type_id == EventTypeTable.id) # 关联et2子查询,匹配event_type和最新创建时间两个关联条件 .join( et2_subquery, (et2_subquery.c.event_type == EventTypeTable.event_type) & (et2_subquery.c.LatestCreatedAt == EventTypeTable.created_at) ) .all() )
逻辑说明
- 子查询通过
label("LatestCreatedAt")给聚合结果命名,和原生SQL里的AS LatestCreatedAt语义完全一致,调用.subquery()生成可关联的SQL层面虚拟表,不会提前拉取数据到内存 - 两次内连接都显式指定了关联条件,和原生SQL的on逻辑完全匹配,不会出现隐式关联导致的结果错误
- 最终查询仅返回EventTable的所有字段,和原生SQL
SELECT ev.*的返回结果完全一致,执行性能和原生SQL无差异
内容的提问来源于stack exchange,提问作者Akihero3
相关产品推荐
相关产品推荐

