You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python Sqlalchemy Postgres 如何存储子查询结果避免重复执行

解决方案

核心方法:使用CTE(公用表达式)复用子查询

在SQLAlchemy中可以通过.cte()方法将重复使用的子查询定义为公用表达式,PostgreSQL在执行时只会对CTE计算一次结果,后续所有引用都会复用该结果,完美解决子查询重复执行问题。

修改后代码示例

仅需要在原有代码基础上做少量调整:

from sqlalchemy.sql.schema import ForeignKey
from sqlalchemy import Column, Integer, Text
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.sql.expression import select, union

Base = declarative_base()
class Table1(Base):
    __tablename__ = 'table1'
    id = Column(Integer, primary_key=True)
    uuid = Column(Text, unique=True, nullable=False)
    
class Table2(Base):
    __tablename__ = 'table2'
    id = Column(Integer, primary_key=True)
    uuid = Column(Text, unique=True, nullable=False)
    
class Table3(Base):
    __tablename__ = 'table3'
    id = Column(Integer, primary_key=True)
    uuid = Column(Text, unique=True, nullable=False)
    
class Table4(Base):
    __tablename__ = 'table4'
    id = Column(Integer, primary_key=True)
    type = Column(Text, nullable=False)

class Table5(Base):
    __tablename__ = 'table5'
    id = Column(Integer, primary_key=True)
    res_id = Column(Integer, ForeignKey('table4.id'), nullable=False)
    value = Column(Text, nullable=False)

class Table1Map(Base):
    __tablename__ = 'table1_map'
    id = Column(Integer, ForeignKey('table4.id'), primary_key=True, nullable=False)
    map_id = Column(Integer, ForeignKey('table1.id'), primary_key=True, unique=True, nullable=False)

class Table2Map(Base):
    __tablename__ = 'table2_map'
    id = Column(Integer, ForeignKey('table4.id'), primary_key=True, nullable=False)
    map_id = Column(Integer, ForeignKey('table2.id'), primary_key=True, unique=True, nullable=False)
    
class Table3Map(Base):
    __tablename__ = 'table3_map'
    id = Column(Integer, ForeignKey('table4.id'), primary_key=True, nullable=False)
    map_id = Column(Integer, ForeignKey('table3.id'), primary_key=True, unique=True, nullable=False)

# 原有子查询定义
sub_query = select([Table5.__table__.c.id]).where(Table5.__table__.c.value=='somevalue')
# 新增:将子查询转为可复用的CTE
sub_query_cte = sub_query.cte('t5_ids')

subquery_1 = select([Table1.__table__.c.uuid.label("map_id"), Table1Map.__table__.c.id.label("id")]).select_from(Table1.__table__.join(Table1Map.__table__, Table1Map.__table__.c.map_id==Table1.__table__.c.id)).where(Table1Map.__table__.c.id.in_(sub_query_cte))
subquery_2 = select([Table2.__table__.c.uuid.label("map_id"), Table2Map.__table__.c.id.label("id")]).select_from(Table2.__table__.join(Table2Map.__table__, Table2Map.__table__.c.map_id==Table2.__table__.c.id)).where(Table2Map.__table__.c.id.in_(sub_query_cte))
subquery_3 = select([Table3.__table__.c.uuid.label("map_id"), Table3Map.__table__.c.id.label("id")]).select_from(Table3.__table__.join(Table3Map.__table__, Table3Map.__table__.c.map_id==Table3.__table__.c.id)).where(Table3Map.__table__.c.id.in_(sub_query_cte))

main_query = union(subquery_1, subquery_2, subquery_3)
print(main_query)

生成的SQL结构

调整后生成的SQL会将公共子查询提前到WITH块中,仅执行一次:

WITH t5_ids AS (
    SELECT TABLE5.ID
    FROM TABLE5
    WHERE TABLE5.VALUE = 'some_value'
)
SELECT TABLE1.UUID AS MAP_ID,
    TABLE1_MAP.ID AS ID
FROM TABLE1
JOIN TABLE1_MAP ON TABLE1_MAP.MAP_ID = TABLE1.ID
WHERE TABLE1_MAP.ID IN (SELECT id FROM t5_ids)
UNION
SELECT TABLE2.UUID AS MAP_ID,
    TABLE2_MAP.ID AS ID
FROM TABLE2
JOIN TABLE2_MAP ON TABLE2_MAP.MAP_ID = TABLE2.ID
WHERE TABLE2_MAP.ID IN (SELECT id FROM t5_ids)
UNION
SELECT TABLE3.UUID AS MAP_ID,
    TABLE3_MAP.ID AS ID
FROM TABLE3
JOIN TABLE3_MAP ON TABLE3_MAP.MAP_ID = TABLE3.ID
WHERE TABLE3_MAP.ID IN (SELECT id FROM t5_ids)

补充说明

如果使用SQLAlchemy 2.0版本,仅需要将select([列])的写法调整为select(列)即可,CTE的使用方式完全一致。


内容的提问来源于stack exchange,提问作者Sakthi Vel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.01 11:54:03