如何在SQLAlchemy中获取指定属性无重复的ORM对象列表
在SQLAlchemy中获取指定字段无重复的记录数组
要实现按email字段去重,保留每个邮箱对应的一条用户记录(如示例中保留Bob而非John),可以用以下几种方法:
方法1:子查询+分组取主键(通用所有数据库)
假设User表有自增主键id,通过子查询获取每个邮箱对应的最小id,再关联查询完整用户记录:
from sqlalchemy import func, select # 子查询:分组获取每个email对应的最小用户ID subquery = select(func.min(User.id)).group_by(User.email).subquery() # 主查询:筛选出对应ID的用户 unique_users = session.query(User).filter(User.id.in_(subquery)).all()
这种方式兼容性强,适用于所有数据库,且能明确控制保留哪条记录(通过取最小/最大主键)。
方法2:PostgreSQL专属的distinct_on
如果使用PostgreSQL,可以直接用distinct_on指定去重字段,结合排序确保返回预期记录:
# 按email去重,保留每个邮箱分组中id最小的用户 unique_users = session.query(User).distinct(User.email).order_by(User.email, User.id).all()
distinct_on会保留每个分组中排序后的第一条记录,必须配合order_by使用,否则结果不确定。
方法3:窗口函数(适用于复杂排序场景)
如果需要更灵活的排序规则(如按创建时间排序),可以用窗口函数给每个邮箱分组的记录编号,再筛选编号为1的记录:
from sqlalchemy import over, row_number # 子查询:给每个email分组的记录按id排序并编号 ranked_subquery = session.query( User, row_number().over(partition_by=User.email, order_by=User.id).label('row_num') ).subquery() # 筛选每个分组的第一条记录 unique_users = session.query(User).join( ranked_subquery, User.id == ranked_subquery.c.id ).filter(ranked_subquery.c.row_num == 1).all()
注意事项
- 无论哪种方法,都必须指定排序规则(如
id、创建时间),否则数据库返回的去重后记录是随机的,无法保证符合预期。 - 如果
User表没有主键,可以用其他唯一标识字段替代id进行筛选。
内容的提问来源于stack exchange,提问作者a55le
相关产品推荐
相关产品推荐

