gpt4 book ai didi

sql - oracle sql查询时间段集合的并集

转载 作者:行者123 更新时间:2023-12-01 00:10:31 24 4
gpt4 key购买 nike

我有一个 oracle 数据库,里面有以下表格。如何计算每个房间的使用时间?
每个房间的时间段可能会重叠,
表结构如下。

t_room_electricity

+------------+--------------------+--------------------+
| roomcode | starttime | endtime |
+------------+--------------------+--------------------+
| 123 | 2019/5/10 10:00:00 | 2019/5/10 11:30:00 |
| 123 | 2019/5/10 10:30:00 | 2019/5/10 11:00:00 |
| 456 | 2019/5/10 11:00:00 | 2019/5/10 12:00:00 |
| 456 | 2019/5/10 13:00:00 | 2019/5/10 14:00:00 |
| 456 | 2019/5/10 13:30:00 | 2019/5/10 15:00:00 |
| 789 | 2019/6/10 14:22:00 | 2019/6/10 14:26:00 |
| 789 | 2019/6/10 14:31:00 | 2019/6/10 14:36:00 |
| 886 | 2019/6/10 14:32:00 | 2019/6/10 14:35:00 |
+------------+--------------------+--------------------+

最佳答案

更新答案以迎合 OP 提到的情况。

使用 MATCH_RECOGNIZE

  with data
as (
select *
from t_room_electricity
match_recognize(
partition by roomcode
order by starttime
measures
first(starttime) f_starttime
,last(starttime) l_starttime
,first(endtime) f_endtime
,last(endtime) l_endtime
,min(starttime) as min_starttime
,max(endtime) as max_endtime
,match_number() as mn
,classifier() as cls
pattern(strt group1*)
define group1
as starttime<first(endtime)
)
)
select roomcode
,round(sum((max_endtime-min_starttime)*24*60)) as diff_in_minutes
from data
group by roomcode

见输出
https://dbfiddle.uk/?rdbms=oracle_18&fiddle=783140ede5dfbf8088a6ce77232ecef7

使用 SQL
select x.roomcode
,count(distinct x.minutes_worked)
from (
select a.roomcode
,a.starttime
,a.endtime
,a.starttime + lvl/24/60 as minutes_worked
from t_room_electricity a
join (select level as lvl
from dual
connect by level<=24*60
)b
on b.lvl<=to_number((a.endtime-a.starttime)*24*60)
)x
group by x.roomcode

见输出..
https://dbfiddle.uk/?rdbms=oracle_11.2&fiddle=2add9344f1335376b2fe32df21f769d6

更新的答案以迎合重叠,(基于新的记录集)
456 | 2019/5/10 11:00:00 | 2019/5/10 12:00:00 |
456 | 2019/5/10 13:00:00 | 2019/5/10 14:00:00 |
456 | 2019/5/10 13:30:00 | 2019/5/10 15:00:00 |
456 | 2019/5/10 13:45:00 | 2019/5/10 15:05:00 |

考虑到重叠,下面的查询可以达到预期的结果
select roomcode
,sum(round(time_in_minutes))
from (
select roomcode
,eventdate
,case when start_flag=1
and (lag(start_flag) over(partition by roomcode order by eventdate asc) = 0
or lag(start_flag) over(partition by roomcode order by eventdate asc) is null)
then null
else (eventdate
-
lag(eventdate) over(partition by roomcode order by eventdate asc)
)*24*60
end as time_in_minutes
from (
select roomcode,starttime as eventdate,1 as start_flag from t_room_electricity
union all
select roomcode,endtime as eventdate,0 as start_flag from t_room_electricity
)x
)y
group by roomcode


+----------+-----------------------------+
| ROOMCODE | SUM(ROUND(TIME_IN_MINUTES)) |
+----------+-----------------------------+
| 123 | 90 |
| 456 | 185 |
| 789 | 9 |
| 886 | 3 |
+----------+-----------------------------+

这首先创建一个内部块,将每个 eventdatetime 存储到名为 EventDate 的单个列中。
然后步骤是检查前一个事件是否为封闭边界(即start_flag=1),如果是则开始计数,否则继续计算前一个事件之间的差值(以分钟为单位)

在此之后,结果按房间代码分组并汇总 time_in_minutes

https://dbfiddle.uk/?rdbms=oracle_11.2&fiddle=650b4f0ad7304d7f44e7fabbca160a90

旧答案
您可以通过使用 group by 表达式来实现这一点,如下所示
select roomcode,sum((endtime-starttime)*24*60) as diff_in_minutes
from t_room_electricity
group by roomcode

+----------+-----------------+
| ROOMCODE | DIFF_IN_MINUTES |
+----------+-----------------+
| 123 | 120 |
| 789 | 9 |
| 456 | 210 |
| 886 | 3 |
+----------+-----------------+

请参阅 dbfiddle 链接。
https://dbfiddle.uk/?rdbms=oracle_11.2&fiddle=16fd05220157fd274cf0fab4e61c8802

关于sql - oracle sql查询时间段集合的并集,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59206727/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com