SQLAlchemy中如何将外键关联表的字段求和值作为主表行的属性?
SQLAlchemy子表字段求和关联到主表的实现方法
首先给出示例对应的基础ORM模型定义:
from sqlalchemy import Column, Integer, String, ForeignKey, func, select from sqlalchemy.orm import relationship from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.ext.hybrid import hybrid_property Base = declarative_base() # 主表模型 class Table1(Base): __tablename__ = "table1" id = Column(Integer, primary_key=True) name = Column(String) description = Column(String) # 关联子表 table2_items = relationship("Table2", backref="table1") # 子表模型 class Table2(Base): __tablename__ = "table2" id = Column(Integer, ForeignKey("table1.id"), primary_key=True) value = Column(Integer)
方法1:临时关联聚合查询
适合单次查询场景,直接在查询语句中关联子表做聚合计算:
# session为已初始化的SQLAlchemy会话实例 result = session.query( Table1.id, Table1.name, Table1.description.label("desc"), func.sum(Table2.value).label("sum(value)") ).join( Table2, Table1.id == Table2.id ).filter( Table1.id == 1 ).group_by( Table1.id, Table1.name, Table1.description ).first() # 输出结果:(1, 'test1', 'desc1', 11) print(result)
如果需要保留无关联子表的主表记录,求和返回0,改用外连接加空值处理:
result = session.query( Table1.id, Table1.name, Table1.description.label("desc"), func.coalesce(func.sum(Table2.value), 0).label("sum(value)") ).outerjoin( Table2, Table1.id == Table2.id ).filter( Table1.id == 1 ).group_by( Table1.id ).first()
方法2:混合属性复用求和逻辑
如果需要频繁使用该求和字段,可以在主表模型中定义混合属性,简化后续查询逻辑。
在Table1模型中新增以下代码:
@hybrid_property def value_sum(self): # 实例层面的求和逻辑,适用于已经加载了子表数据的场景 return sum(item.value for item in self.table2_items) @value_sum.expression def value_sum(cls): # SQL表达式层面的求和逻辑,适用于查询语句中直接调用 return select(func.sum(Table2.value)).where(Table2.id == cls.id).scalar_subquery()
后续查询可直接调用该属性:
# 查询单条主表记录带求和值 item = session.query(Table1, Table1.value_sum).filter(Table1.id == 1).first() # 输出:test1 11 print(item.Table1.name, item.value_sum) # 批量查询所有主表记录带求和值 all_items = session.query(Table1.id, Table1.name, Table1.value_sum).all()
内容的提问来源于stack exchange,提问作者MISHANDLED
相关产品推荐
相关产品推荐

