用户提交表单,因此我有表单表:
date user name phone
2016-01-01 1 NULL 1234
2016-02-02 1 NULL 5678
2016-03-03 1 John NULL
2016-04-04 2 Ken NULL
我想获取按用户分组的所有可用最新用户数据:
user name phone
1 John 5678
2 Ken NULL
如果用户为同一个字段输入了不同的数据 - 我想获得最新的数据。
例如 - 用户1提交了电话1234,然后提交了5678 - 所以我只需要5678。
是否可以在没有自联接和子查询的情况下使用PostgreSQL单一查询获得结果?聚合函数的某种组合?
P.S。这就是为什么这个问题与类似的不同:简单的“distinct on”没有帮助,因为它提供了最后的值,即使它们是空值。
答案 0 :(得分:2)
在首先给出非空值的顺序上使用first_value()
:
with my_table (date, user_id, name, phone) as (
values
('2016-01-01', 1, NULL, '1234'),
('2016-02-02', 1, NULL, '5678'),
('2016-03-03', 1, 'John', NULL),
('2016-04-04', 2, 'Ken', NULL),
('2016-02-05', 3, NULL, NULL),
('2016-03-06', 3, 'Susan', '4444'),
('2016-04-07', 3, 'Alice', '5555')
)
select distinct on (user_id)
user_id,
first_value(name) over (partition by user_id order by name is null, date desc) as name,
first_value(phone) over (partition by user_id order by phone is null, date desc) as phone
from my_table
order by user_id, date desc
user_id | name | phone
---------+-------+-------
1 | John | 5678
2 | Ken |
3 | Alice | 5555
(3 rows)
答案 1 :(得分:0)
试试这个:
select
usr, name, phone
from (
select
usr, name,
row_number() over (partition by usr order by date desc) rn,
first_value(phone) over (
partition by usr
order by case when phone is null
then 1 else 0 end, date desc
) phone
from your_table t
) t where rn = 1;
row_number
以每个用户的日期顺序分配行号以通过过滤获取最新行,并通过条件顺序获取first_value
以获取最新的非空电话号码。此外,类似的逻辑可以应用于name以在需要时获取最新的非空值列。