I was trying to do something like the original question: join a filtered table with another filtered table using an outer join. I was struggling because it's not at all obvious how to:
- create a SQLAlchemy query that returns entities from both tables. @zzzeek's answer showed me how to do that:
get_session().query(A, B)
.
- use a query as a table in such a query. @zzzeek's answer showed me how to do that too:
filtered_a = aliased(A).filter(...).subquery()
.
- use an OUTER join between the two entities. Using
select_from()
after outerjoin()
destroys the join condition between the tables, resulting in a cross join. From @zzzeek answer I guessed that if a
is aliased(), then you can include a
in the query() and also .outerjoin(a), and it won't be joined a second time, and that appears to work.
Following either of @zzzeek's suggested approaches directly resulted in a cross join (combinatorial explosion), because one of my models uses inheritance, and SQLAlchemy added the parent tables outside the inner SELECT without any conditions! I think this is a bug in SQLAlchemy. The approach that I adopted in the end was:
filtered_a = aliased(A, A.query().filter(...)).subquery("filtered_a")
filtered_b = aliased(B, B.query().filter(...)).subquery("filtered_b")
query = get_session().query(filtered_a, filtered_b)
query = query.outerjoin(filtered_b, filtered_a.relation_to_b)
query = query.order_by(filtered_a.some_column)
for a, b in query:
...