每 table 行创建 n 分钟间隔

Creating n minute intervals per table row

我正在尝试根据 table.

获取时间间隔

我的来源 table 是这样的:

ID OTHER_DATA TIME_BEG TIME_END DURATION
1 abcd 10:00 11:00 15
2 xyzt 16:00 17:00 30

期望的输出:

ID OTHER_DATA ITVL_BEG ITVL_END
1 abcd 10:00 10:15
1 abcd 10:15 10:30
1 abcd 10:30 10:45
1 abcd 10:45 11:00
2 xyzt 16:00 16:30
2 xyzt 16:30 17:00

TIME_BEGTIME_ENDVARCHAR 列,但我也将它们设为 DAY TO SECOND INTERVAL,此处未显示(TIME_BEG_INT 和 TIME_END_INT)。

基本上我需要将每一行复制 TRUNC (EXTRACT (DAY FROM 24 * 60 * (TIME_END_INT - TIME_BEG_INT)) / DURATION) 次并将这个*DURATION 添加到我的日期中,一次 SQL.

感谢任何帮助。

如果您使用间隔:

CREATE TABLE table_name (ID, OTHER_DATA, TIME_BEG, TIME_END, DURATION) AS
SELECT 1, 'abcd', INTERVAL '10:00' HOUR TO MINUTE, INTERVAL '11:00' HOUR TO MINUTE, INTERVAL '15' MINUTE FROM DUAL UNION ALL
SELECT 2, 'xyzt', INTERVAL '16:00' HOUR TO MINUTE, INTERVAL '17:00' HOUR TO MINUTE, INTERVAL '30' MINUTE FROM DUAL;

那么你可以使用:

WITH range (ID, OTHER_DATA, TIME_BEG, TIME_INT_END, TIME_END, DURATION) AS (
  SELECT ID,
         OTHER_DATA,
         TIME_BEG,
         LEAST(time_beg + duration, time_end),
         TIME_END,
         DURATION
  FROM   table_name
UNION ALL
  SELECT ID,
         OTHER_DATA,
         TIME_INT_END,
         LEAST(time_int_end + duration, time_end),
         TIME_END,
         DURATION
  FROM   range
  WHERE  time_int_end < time_end
)
SEARCH DEPTH FIRST BY id SET id_order
SELECT ID,
       OTHER_DATA,
       TIME_BEG AS itvl_beg,
       TIME_INT_END AS itvl_end
FROM   range;

输出:

ID OTHER_DATA ITVL_BEG ITVL_END
1 abcd +000000000 10:00:00.000000000 +000000000 10:15:00.000000000
1 abcd +000000000 10:15:00.000000000 +000000000 10:30:00.000000000
1 abcd +000000000 10:30:00.000000000 +000000000 10:45:00.000000000
1 abcd +000000000 10:45:00.000000000 +000000000 11:00:00.000000000
2 xyzt +000000000 16:00:00.000000000 +000000000 16:30:00.000000000
2 xyzt +000000000 16:30:00.000000000 +000000000 17:00:00.000000000

如果您的值是字符串,那么您可以先将它们转换为区间:

CREATE TABLE table_name (ID, OTHER_DATA, TIME_BEG, TIME_END, DURATION) AS
SELECT 1, 'abcd', '10:00', '11:00', 15 FROM DUAL UNION ALL
SELECT 2, 'xyzt', '16:00', '17:00', 30 FROM DUAL;
WITH data(ID, OTHER_DATA, TIME_BEG, TIME_END, DURATION) AS (
  SELECT ID,
         OTHER_DATA,
         TO_DSINTERVAL('0 '||TIME_BEG||':00'),
         TO_DSINTERVAL('0 '||TIME_END||':00'),
         NUMTODSINTERVAL(DURATION, 'MINUTE')
  FROM   table_name
),
range (ID, OTHER_DATA, TIME_BEG, TIME_INT_END, TIME_END, DURATION) AS (
  SELECT ID,
         OTHER_DATA,
         TIME_BEG,
         LEAST(time_beg + duration, time_end),
         TIME_END,
         DURATION
  FROM   data
UNION ALL
  SELECT ID,
         OTHER_DATA,
         TIME_INT_END,
         LEAST(time_int_end + duration, time_end),
         TIME_END,
         DURATION
  FROM   range
  WHERE  time_int_end < time_end
)
SEARCH DEPTH FIRST BY id SET id_order
SELECT ID,
       OTHER_DATA,
       TIME_BEG AS itvl_beg,
       TIME_INT_END AS itvl_end
FROM   range;

db<>fiddle here

这是基于预间隔DATE计算

经典解决方案
with time_int(ID, OTHER_DATA, ITVL_BEG, ITVL_END, DURATION, TIME_END) as (
select 
 ID, OTHER_DATA, TIME_BEG, 
 to_char(to_date(time_beg,'HH24:mi')+duration/(24*60),'HH24:mi'), 
 DURATION, TIME_END 
from tab
union all
select 
 ID, OTHER_DATA, ITVL_END, 
 to_char(to_date(ITVL_END,'HH24:mi')+duration/(24*60),'HH24:mi'), 
 DURATION, TIME_END 
from time_int
where ITVL_END <= TIME_END
)
select 
   ID, OTHER_DATA, ITVL_BEG, ITVL_END
from time_int
order by 1,3;

        ID OTHE ITVL_ ITVL_
---------- ---- ----- -----
         1 abcd 10:00 10:15
         1 abcd 10:15 10:30
         1 abcd 10:30 10:45
         1 abcd 10:45 11:00
         1 abcd 11:00 11:15
         2 xyzt 16:00 16:30
         2 xyzt 16:30 17:00
         2 xyzt 17:00 17:30

一个recursive CTEstep一起使用,根据下面的计算得到下一个区间边界(假设你的时间是存储为 VARCHAR2)

to_char(to_date(time_beg,'HH24:mi')+duration/(24*60),'HH24:mi')

请注意,您可以将 10:00 转换为 日期 并且 Oracle 提供了默认缺失的日、月和年,您不需要这些,因为在增加 duration 你转换回 HH24:MI 字符串。