dein.fr

Writing a subquery with SQLAlchemy core

Charles-Axel Dein
today-i-learned

We have three tables:

  • Folders (id, company_id)
  • Milestones (id, is_done, value: i.e. when the milestone will happen)
  • Members (folder_id, user_id): a member of this folder

A folder has multiple milestones and multiple members. We would like to get a list of (folder.id, max(milestone.value), member.user_id) for each folder ID and member user ID.

As usual with SQLAlchemy, it is a good idea to start by writing the query in plain SQL. Here's one way to do it:

select f1.*, m.user_id from (
    select f.id, max(m.value)
    from folders f
    join milestones m on m.folder_id = f.id
    where f.company_id = :id group by f.id)
as f1

left join folders_members m on m.folder_id = f1.id
order by f1.id

And here's how to write it with SQLAlchemy core:

f = t_folders.c
m = t_milestones.c
members_t = t_folders_members

f1 = (
    select([f.id, func.max(m.value).label("value")])
    .select_from(t_folders.join(t_milestones, f.id == m.folder_id))
    .where(
        and_(
            f.company_id == company_id,
            m.is_done.is_(False),
        )
    )
    .group_by(f.id)
).alias("f1")
f2 = select([f1.c.id, f1.c.value, members_t.c.id]).select_from(
    f1.join(members_t, members_t.c.folder_id == f1.c.id)
)

res = self.session.execute(f2)