如何用SQL将表每行按指定时长拆分为多个连续分钟级时间区间行
时间区间拆分SQL实现方案
以下方案适配Oracle数据库,支持单条SQL完成需求,无需依赖额外辅助表:
方案1:递归CTE写法(适配Oracle 11gR2及以上版本)
写法逻辑更简洁直观,递归生成所有符合要求的时间区间:
WITH RECURSIVE split_intervals AS ( -- 锚点节点:生成每行的第一个时间区间 SELECT ID, OTHER_DATA, TIME_BEG_INT AS ITVL_BEG_INT, TIME_BEG_INT + NUMTODSINTERVAL(DURATION, 'MINUTE') AS ITVL_END_INT, TIME_END_INT FROM 你的源表名 UNION ALL -- 递归节点:持续生成后续区间直到达到结束时间 SELECT ID, OTHER_DATA, ITVL_END_INT AS ITVL_BEG_INT, ITVL_END_INT + NUMTODSINTERVAL(DURATION, 'MINUTE') AS ITVL_END_INT, TIME_END_INT FROM split_intervals WHERE ITVL_END_INT + NUMTODSINTERVAL(DURATION, 'MINUTE') <= TIME_END_INT ) SELECT ID, OTHER_DATA, -- 将INTERVAL类型转换为HH24:MI格式字符串输出 TO_CHAR(TRUNC(SYSDATE) + ITVL_BEG_INT, 'HH24:MI') AS ITVL_BEG, TO_CHAR(TRUNC(SYSDATE) + ITVL_END_INT, 'HH24:MI') AS ITVL_END FROM split_intervals ORDER BY ID, ITVL_BEG;
注意:请将代码中的
你的源表名替换为实际的源数据表名称。
方案2:层级查询写法(兼容Oracle全版本)
如果使用的Oracle版本不支持递归CTE,可以改用CONNECT BY层级查询实现:
SELECT t.ID, t.OTHER_DATA, TO_CHAR(TRUNC(SYSDATE) + t.TIME_BEG_INT + NUMTODSINTERVAL(lv * t.DURATION, 'MINUTE'), 'HH24:MI') AS ITVL_BEG, TO_CHAR(TRUNC(SYSDATE) + t.TIME_BEG_INT + NUMTODSINTERVAL((lv + 1) * t.DURATION, 'MINUTE'), 'HH24:MI') AS ITVL_END FROM 你的源表名 t, -- 生成足够覆盖最大拆分次数的层级序列 (SELECT LEVEL - 1 AS lv FROM DUAL CONNECT BY LEVEL <= ( SELECT MAX(TRUNC(EXTRACT(DAY FROM 24 * 60 * (TIME_END_INT - TIME_BEG_INT)) / DURATION)) + 1 FROM 你的源表名 )) l WHERE l.lv < TRUNC(EXTRACT(DAY FROM 24 * 60 * (t.TIME_END_INT - t.TIME_BEG_INT)) / t.DURATION) ORDER BY t.ID, ITVL_BEG;
内容的提问来源于stack exchange,提问作者Intranet
相关产品推荐
相关产品推荐

