我有一个程序,该程序每分钟通过PING检查网络中计算机的状态。每次它将向数据库插入新行,如下所示(我使用的是postgresql)
id_status status checking_time(timestamp) id_device(int) 1 OK '2017-01-01 00:00:00' 1 2 OK '2017-01-01 00:00:00' 2 3 OK '2017-01-01 00:00:00' 3 4 Failed '2017-01-01 00:01:00' 1 5 OK '2017-01-01 00:01:00' 2 6 OK '2017-01-01 00:01:00' 3 7 Failed '2017-01-01 00:02:00' 1 8 OK '2017-01-01 00:02:00' 2 9 OK '2017-01-01 00:02:00' 3 10 Failed '2017-01-01 00:03:00' 1 11 OK '2017-01-01 00:03:00' 2 12 OK '2017-01-01 00:03:00' 3 13 OK '2017-01-01 00:04:00' 1 14 OK '2017-01-01 00:04:00' 2 15 OK '2017-01-01 00:04:00' 3
我希望结果如下
status from_time(timestamp) to_time(timestamp) id_device(int) 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
dbffile演示
关键是最嵌套的子查询,在该子查询中,我使用两个row_number函数来隔离设备上相同状态的连续出现。一旦有了grn价值,剩下的就很容易了。
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