So I've a query like this
select
user_id,
MAX(
case when attribute = 'one' then newValue else 'No Update' end
) as one,
MAX(
case when attribute = 'two' then newValue else 'No Update' end
) as two,
MAX(
case when attribute = 'thre' then newValue else 'No Update' end
) as thre,
from table
group by user_id
This query returns result as max value for that particular attribute value in different column.
There is an updated_at
column too in this table. Now instead of this, I want that the returned column should contain the latest value according to that updated_at field.
So basically the column one, two and thre
should either contain latest values according to updated_at
field. If no values are there, then the column should contain No Update
string.
What could be the right way?
Example
user_id | attribute | newValue | updatedAt
1 | one | null | 2018-01-20
1 | one | b | 2018-01-21
1 | one | a | 2018-01-22
1 | two | null | 2018-01-23
1 | two | null | 2018-01-24
1 | two | null | 2018-01-25
So for above table the current query would return result as this coz b
is the Max
value for attribute=one
user_id | one | two
1 | b | No Update
But I want the result of column one
to be latest one according to updatedAt
column like this
user_id | one | two
1 | a | No Update
First use DISTINCT ON (user_id, attribute)
to get the only the rows with the latest updatedAt
for each attribute
and then aggregate on the results:
select user_id,
coalesce(max(case when attribute = 'one' then newvalue end), 'No Update') one,
coalesce(max(case when attribute = 'two' then newvalue end), 'No Update') two
from (
select distinct on (user_id, attribute) *
from tablename
order by user_id, attribute, updatedAt desc
) t
group by user_id
See the demo .
Results:
> user_id | one | two
> ------: | :-- | :--------
> 1 | a | No Update
Postgres doesn't have first and last aggregation functions, but you can get similar functionality using arrays:
select user_id,
coalesce((array_agg(newvalue order by updatedAt desc) filter (where attribute = 'one'))[1], 'No update') as one,
coalesce((array_agg(newvalue order by updatedAt desc) filter (where attribute = 'two'))[1], 'No update') as two
from t
group by user_id;
Here is a db<>fiddle.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.