我们说,我有一张包含服务中断列表的表格 字段是:service_id,from_time,to_time。 时间是时间戳类型。
具有这些间隔的服务的状态是" DOWN"。其他时间是" UP"。
我正在寻找一个查询,该查询将返回一个连续的时间间隔列表,表示给定日期和现在之间的特定服务健康状况。
E.g。 该表只包含服务srv1的一次中断:
srv1, 11/01/2017 13:43:32, 11/01/2017 15:20:12, DOWN
然后,来自年度开始的查询结果应如下所示:
srv1, 11/01/2017 15:20:12, 24/07/2017 23:55:00, UP
srv1, 11/01/2017 13:43:31, 11/01/2017 15:20:12, DOWN
srv1, 01/01/2017 00:00:00, 11/01/2017 13:43:31, UP
假设中断不重叠 后续间隔的from_time等于服务的前一时间间隔的to_time 如果服务当前为DOWN,则中断表中的to_time等于NULL。
查询适用于PG 9.6
答案 0 :(得分:1)
基本上,你想要:
以下使用union all
来实现此目的:
select t.*
from t
union all
select id, coalesce(prev_to_time, '2017-01-01'::timestamp) as start_time,
start_time as to_time,
(case when status = 'DOWN' then 'UP' else 'DOWN' end) as status
from (select t.*,
lag(to_time) over (partition by id order by start_time) as prev_to_time,
lag(status) over (partition by id order by start_time) as prev_status
from t
) t
where (prev_to_time is null and start_time <> '2017-01-01'::timestamp or
prev_to_time <> start_time
) and
(prev_status is distinct from status)
union all
select id, max(end_time), now(), 'UP'
from t
group by id
having max(end_time) <> now()
order by id, start_time;
答案 1 :(得分:0)
您可以使用lag()函数回顾上一行。
在这种情况下,例如:
with down as (select *, lag(to_time) over (rows unbounded preceding)
as last_up
from outage order by from_time asc),
full_log as (select host, from_time, to_time, 'down'
AS as status
FROM down
UNION ALL
select host, last_up, from_time, 'up' as status
from down)
select * from full_log order by from_time asc;