SQLAlchemy subquery access outer tables

Question:

I’m having trouble converting this SQL into a valid SQLAlchemy query:

select *
from A
join B on B.Id = (
    select top 1 Id
    from B
    where B.name = A.name
    order by B.date
)

I’ve tried using the subquery but it fails:

query = session.query(A, B)

sub_query = session.query(B)
sub_query = sub_query.filter(B.name == A.name)
sub_query = sub_query.order_by(B.date.desc()).limit(1)
sub_query = sub_query.subquery()

query = query.join(B, B.id == sub_query.c.Id)

By accessing the A in the subquery, SqLAlchemy will add it to the subquery from clause and doesn’t use the A from the outer query.

I’ve seen many SQLAlchemy subquery examples but none of them uses the outer fields.

Asked By: Kavian

||

Answers:

By using correlate(A) in the subquery we tell the SQLAlchemy that reuses A from the outer query.

For making the join work we should access the Id of the subquery, so we should return only Id and use scalar_subquery() to convert the subquery to a scalar subquery:

query = session.query(A, B)

sub_query = session.query(B.Id)
sub_query = sub_query.filter(B.name == A.name)
sub_query = sub_query.order_by(B.date.desc()).limit(1)
sub_query = sub_query.correlate(A)

query = query.join(B, B.id == sub_query.scalar_subquery())
Answered By: Kavian
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.