我有一张桌子:
id; user_id; field_name; value; timestamp
1 1 user_status PENDING 2018-07-31 14:20:28.632838
2 1 selfie APPROVED 2018-07-31 14:20:29.632838
3 2 user_status PENDING 2018-07-31 14:20:31.632838
4 1 passport APPROVED 2018-07-31 14:20:33.632838
5 3 user_status PENDING 2018-07-31 14:20:44.632838
6 2 selfie REJECTED 2018-07-31 14:20:52.632838
7 1 user_status ACTIVATED 2018-07-31 14:20:54.632838
我尝试从以下值中共同选择列:user_status的最新消息,selfie的最新消息,userid的护照组的最新消息:
预期表:
user_id; user_status; selfie; passport
1 ACTIVATED APPROVED APPROVED
2 PENDING REJECTED [null]
3 PENDING [null] [null]
我用了这个sql:
select
user_id,
case when field_name='user_status' then value end as user_status,
case when field_name='selfie' then value end as selfie,
case when field_name='passport' then value end passport
from user_history
group by user_id, field_name, value
但是它提供了一个具有空值且没有不同user_id的表。
user_id; user_status; selfie; passport
1 PENDING [null] [null]
3 PENDING [null] [null]
1 ACTIVATED [null] [null]
2 [null] REJECTED [null]
1 [null] APPROVED [null]
2 PENDING [null] [null]
1 [null] [null] APPROVED
有什么主意吗?谢谢。
答案 0 :(得分:1)
第一个获得最新值的CTE:
db=# select distinct user_id, field_name, first_value(value) over (partition by user_id, field_name order by timestamp desc) from user_history;
user_id | field_name | first_value
---------+-------------+-------------
1 | selfie | APPROVED
1 | passport | APPROVED
2 | selfie | REJECTED
3 | user_status | PENDING
1 | user_status | ACTIVATED
2 | user_status | PENDING
(6 rows)
第二次(从您的尝试开始)以获取人工列:
db=# with c as (select distinct user_id, field_name, first_value(value) over (partition by user_id, field_name order by timestamp desc) from user_history)
select distinct user_id
, case when field_name = 'user_status' then first_value end
, case when field_name = 'selfie' then first_value end
, case when field_name = 'passport' then first_value end
from c
order by user_id;
user_id | case | case | case
---------+-----------+----------+----------
1 | ACTIVATED | |
1 | | APPROVED |
1 | | | APPROVED
2 | PENDING | |
2 | | REJECTED |
3 | PENDING | |
(6 rows)
最终崩溃:
db=# with c as (select distinct user_id, field_name, first_value(value) over (partition by user_id, field_name order by timestamp desc) from user_history)
, ct as (
select distinct user_id
, case when field_name = 'user_status' then first_value end user_status
, case when field_name = 'selfie' then first_value end selfie
, case when field_name = 'passport' then first_value end passport
from c
)
select
user_id
, max(user_status) user_status
, max(selfie)selfie
, max(passport) passport
from ct
group by user_id
order by user_id;
user_id | user_status | selfie | passport
---------+-------------+----------+----------
1 | ACTIVATED | APPROVED | APPROVED
2 | PENDING | REJECTED |
3 | PENDING | |
(3 rows)
答案 1 :(得分:1)
一种方法使用窗口函数-因为first_value()
是窗口函数而不是聚合函数。
您可以按照以下步骤进行操作:
select distinct user_id,
first_value(value) filter (where field_name = 'user_status') over
(partition by user_id order by timestamp desc) as user_status,
first_value(value) filter (where field_name = 'selfie') over
(partition by user_id order by timestamp desc) as selfie,
first_value(value) filter (where field_name = 'passport') over
(partition by user_id order by timestamp desc) as passport
from user_history;
您也可以使用数组来做到这一点:
select user_id,
(array_agg(value order by timestamp desc) filter (where field_name = 'user_status'))[1] as user_status,
(array_agg(value order by timestamp desc) filter (where field_name = 'selfie'))[1] as selfie,
(array_agg(value order by timestamp desc) filter (where field_name = 'passport'))[1] as passport
from user_history
group by user_id;