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.
