计算 Postgresql 中的每日中断
Calculate Daily Outage in Postgresql
例如,我有中断开始日期时间:'2017-09-09 06:56:22' 和结束日期时间:'2017-09-13 14:22:45'。
现在我想每天获取停电持续时间,如果整个停电然后给我'24:00:00'但是如果一天中只有一部分停电然后我们做减法ex:startTime - DayEndTime(StartTime)那个00:00:00 开始日结束。
因此,如果一整天都停电,那么每天都会计算出来 24:00:00.
我如何在 postgresql 中解决这个问题?请帮忙
见下文table
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
你可以只计算差值,只要是一整天就用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;
您可以使用 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;
您可以使用子查询获取每一天的跨度。
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
例如,我有中断开始日期时间:'2017-09-09 06:56:22' 和结束日期时间:'2017-09-13 14:22:45'。 现在我想每天获取停电持续时间,如果整个停电然后给我'24:00:00'但是如果一天中只有一部分停电然后我们做减法ex:startTime - DayEndTime(StartTime)那个00:00:00 开始日结束。 因此,如果一整天都停电,那么每天都会计算出来 24:00:00.
我如何在 postgresql 中解决这个问题?请帮忙
见下文table
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
你可以只计算差值,只要是一整天就用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;
您可以使用 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;
您可以使用子查询获取每一天的跨度。
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