SQL - 按列对两行进行分组,不同列上的值和空值

SQL - Group two rows by columns that value and null on different columns

问题

假设我有一个 table 包含这样的行:

id | country | place | last_action | second_to_last_action
----------------------------------------------------------
1  |   US    |   2   |   reply     | 
1  |   US    |   2   |             |       comment
4  |   DE    |   5   |   reply     | 
4  |         |       |             |       comment

我想做的是将它们按 ID、国家和地点组合起来,这样 last_action 和 second_to_last_action 就会在同一行

id | country | place | last_action | second_to_last_action
----------------------------------------------------------
1  |   US    |   2   |   reply     |      comment
4  |   DE    |   5   |   reply     |      comment

我将如何处理这个问题?我想我在这里需要一个聚合,但我的脑子里一片空白,不知道我应该使用哪个。

可以预料,总会有一对相配的。

背景:

注意:这个 table 是从这样的东西派生出来的:

id | country | place |   action    | time
----------------------------------------------------------
1  |   US    |   2   |   reply     |    16:15
1  |   US    |   2   |   comment   |    15:16
1  |   US    |   2   |   view      |    13:16
4  |   DE    |   5   |   reply     |    17:15
4  |   DE    |   5   |   comment   |    16:16
4  |   DE    |   5   |   view      |    14:12

用于分区的代码是:

row_number() over (partition by id order by time desc) as event_no

然后我通过获取 event_no 1 和 2 获得了最后一个和 second_to_last 操作。因此,如果有更有效的方法在两个不同的列中获取最后两个操作,我会很乐意听到了。

您可以使用聚合修复您的第一个数据:

select id, country, place, max(last_action), max(second_to_last_action)
from derived
group by id, country, place;

您可以使用条件聚合从原始 table 执行此操作:

select id, country, place,
       max(case when seqnum = 1 then action end) as last_action,
       max(case when seqnum = 2 then action end) as second_to_last_action
from (select t.*,
            row_number() over (partition by id order by time desc) as seqnum
      from t
     ) t
group by id, country, place;