Search code examples
sqlpostgresqlgreatest-n-per-group

Can I get objects and their latest related object in one query?


Suppose I have a table of Foos. Each Foo has multiple Bars. I want to return all Foos and the latest Bar for each of them. How can I do this in one PostgreSQL query?

foos

id name
1 Foo1
2 Foo2

bars

id foo_id created_date
1 1 2022-12-02 13:00:00
2 1 2022-12-02 13:30:00
3 2 2022-12-02 14:00:00
4 2 2022-12-02 14:30:00

Expected Result

id name bar.id bar.foo_id bar.created_date
1 Foo1 2 1 2022-12-02 13:30:00
2 Foo2 4 2 2022-12-02 14:30:00

Solution

  • To find the greatest per group first we need to figure

    1. How to define the group, here the each foo id is a group
    2. What is the greatest value, here the greatest value is created_date

    To implement this use the function like ROW_NUMBER for this one define the partition based on foo id and sorting based on created_date desc

    Which in terms of code translates to:

    ROW_NUMBER() OVER(partition by f.id order by b.created_date desc)
    
    with cte as (
    select 
        f.id as foo_id, 
        f.name as foo_name, 
        b.id as bar_id, 
        b.created_date,
        ROW_NUMBER() OVER(partition by f.id order by b.created_date desc) as RNUM 
    from Foos as f join Bars as b on f.id = b.foo_id )
    select 
        foo_id,
        foo_name,
        bar_id,
        created_date
    from cte where RNUM = 1