PostgreSQL:如何在没有自加入的情况下提取所有可用的最新数据?

时间:2017-02-02 18:45:49

标签: postgresql

用户提交表单,因此我有表单表:

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”没有帮助,因为它提供了最后的值,即使它们是空值。

2 个答案:

答案 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以在需要时获取最新的非空值列。