You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

多日期时间范围拆分SQL脚本异常:结果不符合预期需求

SQL跨日期条目拆分脚本问题排查

我编写了如下SQL脚本,用于将单日时间条目保持原样,跨多日的时间条目按日期拆分展开,但当前执行结果不符合预期,正确的拆分结果应覆盖所有涉及的日期,且每日的时间段对应正确。

原SQL脚本:

with  first_step as
(
SELECT  
1 as MY_TYPE,
    2373 as my_id
    ,to_date('15.02.23 17:00'  , 'dd.mm.yyyy HH24:MI') AS  time_from
    ,to_date('17.02.23 12:00' , 'dd.mm.yyyy HH24:MI')AS  time_till
    from dual
    union all
SELECT  
1 as MY_TYPE,
    2373 as my_id
    ,to_date('16.02.23 14:00'  , 'dd.mm.yyyy HH24:MI') AS  time_from
    ,to_date('16.02.23 15:00' , 'dd.mm.yyyy HH24:MI')AS  time_till
    from dual
    union all
SELECT  
0 as MY_TYPE,
    2373 as my_id
    ,to_date('14.02.23 22:00'  , 'dd.mm.yyyy HH24:MI') AS  time_from
    ,to_date('16.02.23 18:00' , 'dd.mm.yyyy HH24:MI')AS  time_till
    from dual
),
second_step as 
(
select 
MY_TYPE,
my_id,
to_date(to_char(time_from +(column_value-1), 'dd.mm.yyyy'),'dd.mm.yyyy') AS  my_date,
case when trunc(time_from)  < to_date(to_char(time_from +(column_value-1), 'dd.mm.yyyy'),'dd.mm.yyyy') then '00:00' else to_char(time_from,'HH24:MI') end time_from,
case when trunc(time_till) > to_date(to_char(time_from +(column_value-1), 'dd.mm.yyyy'),'dd.mm.yyyy') then '23:59' else replace(to_char(time_till,'HH24:MI'),'00:00','23:59') end time_till
from first_step 
   CROSS JOIN TABLE ( CAST(MULTISET(
                SELECT
                   level
                from
                    dual
                CONNECT BY time_from  + level-1    <=    time_till
            ) AS sys.odcinumberlist) ) n
)
select * from second_step 
order by 
my_date,time_from, time_till

脚本存在的核心问题

  • 日期生成逻辑错误
    原脚本中CONNECT BY time_from + level-1 <= time_till按完整datetime累加判断,会导致跨日但结束时间早于起始时间当天同一小时的条目无法生成最后一天的行。例如第一个条目time_from=15.02.23 17:00、time_till=17.02.23 12:00,当level=3时,time_from+2等于17.02.23 17:00,晚于time_till的17.02.23 12:00,因此不会生成17号的行,导致拆分结果缺失最后一天的数据。

  • 日期计算冗余且易出错
    to_date(to_char(time_from +(column_value-1), 'dd.mm.yyyy'),'dd.mm.yyyy')写法冗余,等价于更简洁高效的trunc(time_from) + (column_value - 1),多次转换容易引发格式或隐式转换问题。

  • 时间段判断逻辑冗余
    原脚本重复计算to_date(to_char(time_from +(column_value-1), 'dd.mm.yyyy'),'dd.mm.yyyy'),增加了不必要的计算开销。


修正后的SQL脚本

with  first_step as
(
SELECT  
1 as MY_TYPE,
    2373 as my_id
    ,to_date('15.02.23 17:00'  , 'dd.mm.yyyy HH24:MI') AS  time_from
    ,to_date('17.02.23 12:00' , 'dd.mm.yyyy HH24:MI')AS  time_till
    from dual
    union all
SELECT  
1 as MY_TYPE,
    2373 as my_id
    ,to_date('16.02.23 14:00'  , 'dd.mm.yyyy HH24:MI') AS  time_from
    ,to_date('16.02.23 15:00' , 'dd.mm.yyyy HH24:MI')AS  time_till
    from dual
    union all
SELECT  
0 as MY_TYPE,
    2373 as my_id
    ,to_date('14.02.23 22:00'  , 'dd.mm.yyyy HH24:MI') AS  time_from
    ,to_date('16.02.23 18:00' , 'dd.mm.yyyy HH24:MI')AS  time_till
    from dual
),
second_step as 
(
select 
    MY_TYPE,
    my_id,
    trunc(time_from) + (column_value - 1) AS my_date,
    case 
        when trunc(time_from) < trunc(time_from) + (column_value - 1) then '00:00' 
        else to_char(time_from,'HH24:MI') 
    end time_from,
    case 
        when trunc(time_till) > trunc(time_from) + (column_value - 1) then '23:59' 
        else replace(to_char(time_till,'HH24:MI'),'00:00','23:59') 
    end time_till
from first_step 
   CROSS JOIN TABLE ( CAST(MULTISET(
                SELECT level
                from dual
                -- 按日期截断后的天数差生成需要的行数,确保覆盖所有涉及的日期
                CONNECT BY level <= trunc(time_till) - trunc(time_from) + 1
            ) AS sys.odcinumberlist) ) n
)
select * from second_step 
order by my_date, time_from, time_till

修正说明

  1. 调整CONNECT BY条件为level <= trunc(time_till) - trunc(time_from) + 1,按日期截断后的天数差生成条目,确保所有涉及的日期都能生成对应的行。
  2. 简化my_date的计算方式为trunc(time_from) + (column_value - 1),避免冗余的日期转换。
  3. 简化时间段判断中的日期对比逻辑,直接使用截断后的日期进行判断,提升脚本可读性和执行效率。

内容的提问来源于stack exchange,提问作者kirilb

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 17:01:13