I need to query multiple entities, something like session.query(Entity1, Entity2)
, only from a subquery rather than directly from the tables. The docs have something about selecting one entity from a subquery but I can’t find how to select more than one, either in the docs or by experimentation.
My use case is that I need to filter the tables underlying the mapped classes by a window function, which in PostgreSQL can only be done in a subquery or CTE.
EDIT: The subquery spans a JOIN of both tables so I can’t just do aliased(Entity1, subquery)
.
Advertisement
Answer
JavaScript
x
41
41
1
from sqlalchemy import *
2
from sqlalchemy.orm import *
3
from sqlalchemy.ext.declarative import declarative_base
4
5
Base = declarative_base()
6
7
class A(Base):
8
__tablename__ = "a"
9
10
id = Column(Integer, primary_key=True)
11
bs = relationship("B")
12
13
class B(Base):
14
__tablename__ = "b"
15
16
id = Column(Integer, primary_key=True)
17
18
a_id = Column(Integer, ForeignKey('a.id'))
19
20
e = create_engine("sqlite://", echo=True)
21
Base.metadata.create_all(e)
22
s = Session(e)
23
s.add_all([A(bs=[B(), B()]), A(bs=[B()])])
24
s.commit()
25
26
# with_labels() here is to disambiguate A.id and B.id.
27
# without it, you'd see a warning
28
# "Column 'id' on table being replaced by another column with the same key."
29
subq = s.query(A, B).join(A.bs).with_labels().subquery()
30
31
32
# method 1 - select_from()
33
print s.query(A, B).select_from(subq).all()
34
35
# method 2 - alias them both. "subq" renders
36
# once because FROM objects render based on object
37
# identity.
38
a_alias = aliased(A, subq)
39
b_alias = aliased(B, subq)
40
print s.query(a_alias, b_alias).all()
41