Home > OS >  Selecting last row for unique index ordered by column
Selecting last row for unique index ordered by column

Time:04-22

Objective

I have a list of payment records that contain account_uuid, price, type & created_at. I need to get a list of the latest payment record specific to each account_uuid where the type = 0.

What I have tried

My first attempt was to ORDER BY on created_at to ensure the latest row was last, then to GROUP BY on account_uuid. The issue is that I would have to add both account_uuid and created_at to the GROUP BY expression which would include multiple records for the account_uuid as it will only group rows when both account_uuid and created_at are the same, which is never.

My second attempt was to SELECT DISTINCT ON account_uuid. This didn't work for the same reason above as it complains I must include my ORDER BY column in my DISTINCT ON expression which would yield the same result.

Sample Data

account_uuid price type created_at (↑)
aa4dd27e-b72a-40fd-bdab-94810e585734 8.96 0 1649840899215
5c5625af-65e5-43d3-a39d-b896cd4d02a3 14.58 0 1649841117203
aa4dd27e-b72a-40fd-bdab-94810e585734 null 2 1649843706217
d8a106f9-dbf2-42f1-ac6b-a17e88700fab 3.939 0 1650434747192
aa4dd27e-b72a-40fd-bdab-94810e585734 14.58 0 1650438658596

Sample Result (Desired)

account_uuid price type (=0) created_at (↑)
5c5625af-65e5-43d3-a39d-b896cd4d02a3 14.58 0 1649841117203
d8a106f9-dbf2-42f1-ac6b-a17e88700fab 3.939 0 1650434747192
aa4dd27e-b72a-40fd-bdab-94810e585734 14.58 0 1650438658596

Problem / Question

What I am trying to achieve is the sample result which you can see returns only the latest row for the account_uuid where type is 0 and created_at is ascending. Best case I would like to do it without any joins/subqueries but am happy for just getting it working.

Thank You

CodePudding user response:

Edit: A simpler solution would be:

select distinct on (account_uuid) 
       max(created_at) 
       ,price
       ,type
       ,account_uuid
from tableName
where type = 0
group by price,type,account_uuid

You can achieve this in Postgres without using join/sub-queries by using a combination of DISTINCT ON and window functions. This assumes that you truly want the "latest row where type = 0" and not "If the latest row = 0".

select distinct on (account_uuid) 
       max(created_at) over (partition by account_uuid order by created_at desc)
       ,price
       ,type
       ,account_uuid
from tableName
where type = 0

Fiddle here

CodePudding user response:

You need select using ROW_NUMBER() in a sub query and then in the outer where statement you select RN = 1

There are many code examples of using ROW_NUMBER() if you search for it.

  • Related