2017-09-20 27 views
0

我有例如中断Start DateTime:'2017-09-09 06:56:22'和End DateTime:'2017-09-13 14:22:45'。 现在我想要获得每日停电时间,如果整个停电时间都是'24:00:00',但是如果在一天的部分时间内有停电,那么我们会执行减法,例如:startTime - DayEndTime(StartTime)即在该开始日的结尾00:00:00。 因此,如果每天都有停电,那么每天都会计算24:00:00。在Postgresql中计算日常中断

我如何在postgresql中解决这个问题?请帮助下

StartTime EndTime OutageTime 

2017-09-09 6:56:32 2017-09-10 0:00:00 17:03:28 
2017-09-10 0:00:00 2017-09-11 0:00:00 24:00:00 
2017-09-11 0:00:00 2017-09-12 0:00:00 24:00:00 
2017-09-12 0:00:00 2017-09-13 0:00:00 24:00:00 
2017-09-13 0:00:00 2017-09-13 14:22:45 14:22:45 
+2

请向我们展示一些表格示例数据以及您期望的输出。 –

+0

其第2列'开始日期时间'和'结束日期时间'是计算列。输出是这种格式'hh:mm:ss'的中断时间,请记住'24:00:00'的绝对中断时间,因此只是相同的时间 – Emac4444

+0

请向我们展示一些表格示例数据以及输出正在期待。 –

回答

0
with t (startTime, endTime) as (values 
('2017-09-09 6:56:32'::timestamptz,'2017-09-10 0:00:00'::timestamptz), 
('2017-09-10 0:00:00','2017-09-11 0:00:00'), 
('2017-09-11 0:00:00','2017-09-12 0:00:00'), 
('2017-09-12 0:00:00','2017-09-13 0:00:00'), 
('2017-09-13 0:00:00','2017-09-13 14:22:45')) 
select startTime, endTime, upper(i) - lower(i) as a 
from 
    (
     select tstzrange(startTime, endTime) as tstzr, startTime, endTime 
     from t 
    ) t 
    inner join (
     select tstzrange(d, d + interval '1 day') as d 
     from 
     generate_series (
      (select min(startTime)::date from t), 
      (select max(endTime) from t), 
      '1 day' 
     ) gs (d) 
    ) gs on d && tstzr 
    cross join lateral (
     select tstzr * d as i 
    ) cjl 
; 
     starttime  |  endtime   | a  
------------------------+------------------------+---------- 
2017-09-09 06:56:32-03 | 2017-09-10 00:00:00-03 | 17:03:28 
2017-09-10 00:00:00-03 | 2017-09-11 00:00:00-03 | 1 day 
2017-09-11 00:00:00-03 | 2017-09-12 00:00:00-03 | 1 day 
2017-09-12 00:00:00-03 | 2017-09-13 00:00:00-03 | 1 day 
2017-09-13 00:00:00-03 | 2017-09-13 14:22:45-03 | 14:22:45 
1

见表你可以只计算差值,并与24:00:00取代它时,它是一整天:

SELECT starttime, 
     endtime, 
     CASE endtime - starttime 
      WHEN INTERVAL '1 day' 
      THEN '24:00:00' 
      WHEN INTERVAL '1 day 1 hour' 
      THEN '25:00:00' 
      ELSE CAST(endtime - starttime AS text) 
     END AS outagetime 
FROM outages; 
+0

也许'> = interval'1 day''将是一个更好的主意 - 以防万一 –

+1

@a_horse_with_no_name不知道,也许......但我忘了夏令时时间。 –

+0

否否。如果停电超过一天,则应在第二天的00:00:00截断。所以我们假设有超过1个答案 – Emac4444

0

可以使用generate_series()做到这一点。以下是每天获得结果的逻辑:

select (case when date_trunc('day', g.dte) = date_trunc('day', o.start_time) 
      then g.dte 
      else date_trunc('day', g.dte) 
     end), 
     (case when date_trunc('day', g.dte) < date_trunc('day', o.end_time) 
      then date_trunc('day', g.dte) + interval '1 day' 
      else o.end_time 
     end) 
from outages o, lateral 
    generate_series(start_time, end_time, interval '1 day') g(dte) 
where g.dte < o.end_time; 

您可以使用子查询来获取每天的跨度。