SQLAlchemy ORM 中相同 table 的子查询

Subquery to the same table in SQLAlchemy ORM

大家好SQL炼金大师们, 我只是面临如何在 python 中为 SQL 查询

使用 SQLAlchemy ORM 的问题
SELECT systems.name,
       (
       SELECT date 
       FROM accounting A
       WHERE A.ticker = C.ticker AND A.info = 'Trade_opened'
       ) AS entry,
 C.*
 FROM accounting C
 JOIN systems ON C.system_id = systems.id
 WHERE C.status = 'open'

而且我不能以正确的方式使用 aliased():

    H = aliased(Accounting, name='H')
    C = aliased(Accounting, name='C')

    his = db.session.query(H.date) \
                    .filter(H.ticker == C.ticker, H.info == r'Trade_opened')
    sql = db.session.query(Systems.name, C, his) \
                    .join(Systems, C.system_id == Systems.id) \
                    .filter(C.status == r'Open') \
                    .statement

    print(sql)

你能帮帮我吗?

我认为你需要:

  • scalar_subquery 能够将子查询用作列
  • select_from 能够将连接的“左侧”设置为不同于第一列(即 C 而不是 systems)。

我没有用实际数据对此进行测试,所以我不知道它是否可以正常工作。如果您 post 您的模式和一些测试数据,它会有所帮助。我使用 Account 是因为它有一个简单的复数形式 accounts 来设置测试。


Base = declarative_base()

class Account(Base):
    __tablename__ = 'accounts'
    id = Column(Integer, primary_key=True)
    date = Column(Date)
    ticker = Column(String(length=200))
    info = Column(String(length=200))
    status = Column(String(length=200))
    system = relationship('System', backref='accounts')
    system_id = Column(Integer, ForeignKey('systems.id'))

class System(Base):
    __tablename__ = 'systems'
    id = Column(Integer, primary_key=True)
    name = Column(String(length=200))


with Session(engine) as session:
    C = aliased(Account, name='C')
    A = aliased(Account, name='A')
    date_subq = session.query(A.date).filter(and_(A.ticker == C.ticker, A.info == 'Trade_opened')).scalar_subquery()
    q = session.query(System.name, date_subq.label('entry'), C).select_from(C).join(C.system).filter(C.status == 'open')
    print (q)

格式化SQL:

SELECT 
systems.name AS systems_name,
(SELECT "A".date 
FROM accounts AS "A" WHERE "A".ticker = "C".ticker AND "A".info = %(info_1)s) AS entry,
"C".id AS "C_id",
"C".date AS "C_date",
"C".ticker AS "C_ticker",
"C".info AS "C_info", 
"C".status AS "C_status",
"C".system_id AS "C_system_id" 
FROM accounts AS "C" 
JOIN systems ON systems.id = "C".system_id 
WHERE "C".status = %(status_1)s