Postgresql Table 相同数据最后一次相邻出现和第一行
Postgresql Table Same Data last adjacent occurance and first In One row
我有一个程序,每分钟通过 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
关键是最嵌套的子查询,我在其中使用两个 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
类似问题
SQL query to get min, max rows
我有一个程序,每分钟通过 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
关键是最嵌套的子查询,我在其中使用两个 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
类似问题
SQL query to get min, max rows