SQLAlchemy ORM使用Union合并子查询实现多条件查询求助
解决SQLAlchemy ORM中Union合并查询并指定返回列的问题
首先,咱们来修正你的match_name_prop函数,让它能正确生成Union查询,同时保留后续指定查询列的能力:
def match_name_prop(_name, _prop): # 获取两个基础查询对象 name_query = match_name(_name) prop_query = match_prop(_prop) # 直接调用Query实例的union方法合并两个查询 return name_query.union(prop_query)
两种获取指定列结果的方式
方式1:在Union后的查询上直接指定要返回的实体列
这种方式最简洁,因为合并后的查询依然关联着Foo模型,所以可以直接用with_entities指定需要的字段:
# 获取仅包含id和name的结果集 all_result = match_name_prop(myname, myprop).with_entities(Foo.id, Foo.name).all()
方式2:通过session.query指定列(适合更复杂的场景)
如果你需要结合其他查询逻辑,也可以用session来查询,通过select_from指定Union查询作为数据源:
union_query = match_name_prop(myname, myprop) all_result = session.query(Foo.id, Foo.name).select_from(union_query).all()
为什么你的原写法无法正常工作?
- 错误的Union调用方式:你用了
Query.union([subquery1, subquery2]),这不是SQLAlchemy ORM推荐的用法。正确的做法是调用已有Query实例的union方法,传入另一个Query对象——因为match_name和match_prop已经返回了针对Foo的Query,直接合并它们即可,不需要先转成subquery。 - 不必要的子查询转换:把Query转成subquery后,查询结果会变成匿名的数据库视图列(比如
sqry3.c.id),丢失了和Foo模型的关联,不仅写法繁琐,还容易出错。
额外提示
- 如果不需要自动去重(即允许重复的记录出现在结果中),可以把
union换成union_all,性能会更好一些。 - 确认你的
Foo模型定义中,__table__应该是__tablename__(可能是笔误),否则模型映射会有问题:class Foo(Base): __tablename__ = 'foo_table' # 这里应该是__tablename__而不是__table__ id = Column(Integer, primary_key=True) # 建议加上primary_key,符合ORM最佳实践 name = Column(String) prop = Column(Integer)
内容的提问来源于stack exchange,提问作者mzoll
相关产品推荐
相关产品推荐

