Postgresql表相同的数据最后相邻发生和第一行

Postgresql表相同的数据最后相邻发生和第一行,sql,postgresql,gaps-and-islands,Sql,Postgresql,Gaps And Islands,我有一个程序,通过每分钟PING来检查网络中计算机的状态。 每次它都会向DB插入一个新行,如下所示(我使用的是postgresql) 我希望结果如下 status from_time(timestamp) to_time(timestamp) id_device(int) 如何获得此输出?这是间隙和孤岛问题。可通过以下方式解决此问题: select t.status, t.from_time, coalesce(CAST(lead(from_time) ov

我有一个程序,通过每分钟PING来检查网络中计算机的状态。 每次它都会向DB插入一个新行,如下所示(我使用的是postgresql)

我希望结果如下

status   from_time(timestamp)    to_time(timestamp)      id_device(int)

如何获得此输出?

这是间隙和孤岛问题。可通过以下方式解决此问题:

select t.status, 
   t.from_time, 
   coalesce(CAST(lead(from_time) over (partition by id_device order by from_time) AS varchar(20)), 'NOW') to_date, 
   t.id_device
from
(
    select t.status, min(checking_time) from_time, t.id_device
    from
    (
        select *, row_number() over (partition by id_device, status order by checking_time) - 
                  row_number() over (partition by id_device order by checking_time) grn
        from data
    ) t
    group by t.id_device, grn, t.status
) t
order by  t.id_device, t.from_time

最关键的是最嵌套的子查询,其中我使用两个
row_number
函数来隔离设备上连续出现的相同状态。一旦有了
grn
值,剩下的就很简单了

结果

status  from_time           to_time             id_device
------------------------------------------------------------
OK      2017-01-01 00:00:00 2017-01-01 00:01:00 1
Failed  2017-01-01 00:01:00 2017-01-01 00:04:00 1
OK      2017-01-01 00:04:00 NOW                 1
OK      2017-01-01 00:00:00 NOW                 2
OK      2017-01-01 00:00:00 NOW                 3
类似问题


谢谢@Radim Bača,它的效果很好。
OK       '2017-01-01 00:00:00'   '2017-01-01 00:01:00'   1
Failed   '2017-01-01 00:01:00'   '2017-01-01 00:04:00'   1
OK       '2017-01-01 00:04:00'   NOW                     1

OK       '2017-01-01 00:00:00'   NOW                     2
OK       '2017-01-01 00:00:00'   NOW                     3
select t.status, 
   t.from_time, 
   coalesce(CAST(lead(from_time) over (partition by id_device order by from_time) AS varchar(20)), 'NOW') to_date, 
   t.id_device
from
(
    select t.status, min(checking_time) from_time, t.id_device
    from
    (
        select *, row_number() over (partition by id_device, status order by checking_time) - 
                  row_number() over (partition by id_device order by checking_time) grn
        from data
    ) t
    group by t.id_device, grn, t.status
) t
order by  t.id_device, t.from_time
status  from_time           to_time             id_device
------------------------------------------------------------
OK      2017-01-01 00:00:00 2017-01-01 00:01:00 1
Failed  2017-01-01 00:01:00 2017-01-01 00:04:00 1
OK      2017-01-01 00:04:00 NOW                 1
OK      2017-01-01 00:00:00 NOW                 2
OK      2017-01-01 00:00:00 NOW                 3