“群组”仅包含连续数据

时间:2016-05-17 14:50:46

标签: sql postgresql

我有完整的数据

表t1:

╔════╦═════════╦══════════════════╗
║ id ║ name    ║        dt        ║
╠════╬═════════╬══════════════════╣
║  1 ║  name1  ║ 05/05/2016 10:00 ║
║  2 ║  name2  ║ 07/05/2016 10:00 ║
║  3 ║  name1  ║ 08/05/2016 10:00 ║
║  4 ║  name1  ║ 09/05/2016 10:00 ║
╚════╩═════════╩══════════════════╝

我希望'按顺序分组'或标记每个具有相同名称的'连续'组

这样的事情

╔════════╦════════════════════════════════╦══════════════════════════════╦════════╗
║ name   ║ min dt                         ║ max dt                       ║ agg id ║
╠════════╬════════════════════════════════╬══════════════════════════════╬════════╣
║ name1  ║ 05/05/2016 10:00               ║ 05/05/2016 10:00             ║  {1}   ║
║ name2  ║ 07/05/2016 10:00               ║ 07/05/2016 10:00             ║  {2}   ║
║ name1  ║ 08/05/2016 10:00               ║ 09/05/2016 10:00             ║  {3,4} ║
╚════════╩════════════════════════════════╩══════════════════════════════╩════════╝

或类似的东西

╔═══════════╦════╦═════════╦══════════════════╗
║ group id  ║ id ║ name    ║        dt        ║
╠═══════════╬════╬═════════╬══════════════════╣
║         1 ║  1 ║  name1  ║ 05/05/2016 10:00 ║
║         2 ║  2 ║  name2  ║ 07/05/2016 10:00 ║
║         3 ║  3 ║  name1  ║ 08/05/2016 10:00 ║
║         3 ║  4 ║  name1  ║ 09/05/2016 10:00 ║
╚═══════════╩════╩═════════╩══════════════════╝

在postgres 9.4中有什么可能吗?

thx michal

1 个答案:

答案 0 :(得分:1)

一种方法使用lag()查看名称是否已更改。然后做一个该值的累积和:

select t.*,
       sum(case when name = prev_name then 0 else 1 end) over (order by dt) as grp
from (select t.*,
             lag(name) over (order by dt) as prev_name
      from t1 t
     ) t;

为了获得最小值和最大值的聚合,我更喜欢行号方法的差异:

select name, min(dt), max(dt)
from (select t.*,
             (row_number() over (order by dt) - 
              row_number() over (partition by name order by dt)
             ) as grp 
      from t1 t
     ) t
 group by grp, name;

要了解发生的情况,最好使用单独的行号运行子查询。根据我的经验,当你看到序列及其差异时,你会有一个“啊哈”时刻。