如何在SELECT查询中填补时间间隔?

时间:2017-07-24 11:08:14

标签: sql postgresql

我们说,我有一张包含服务中断列表的表格 字段是: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

2 个答案:

答案 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;
相关问题