【问题标题】:Generate Appointment Time Slots生成预约时间段
【发布时间】:2020-08-08 20:17:18
【问题描述】:

我有如下分支时序视图。日期会根据 sysdate 改变

 TIME_FROM                TIME_TO
 09/08/2020 07:00:00 AM   09/08/2020 02:00:00 PM
 09/08/2020 04:00:00 PM   09/08/2020 06:00:00 PM

我想生成持续时间为 60 分钟的预约空档,如下所示。 60 分钟是可变的,我会将其作为参数传递。我想得到这样的查询结果

7.00 AM
8.00 AM
9.00 AM
10.00 AM
11.00 AM
12.00 PM
1.00 PM
4.00 PM
5.00 PM

排除轮班结束时间(下午 2:00 和下午 6:00)因为没有意义包括它们

【问题讨论】:

    标签: sql oracle oracle12c


    【解决方案1】:

    这是一种递归 CTE 方法:

    with cte (time_from, time_to, lev) as (
          select time_from, time_to, 1 as lev
          from t
          union all
          select time_from + interval '1' hour, time_to, lev + 1
          from cte
          where time_from < time_to - interval '1' hour
         )
    select time_from
    from cte;
    

    And a db<>fiddle.

    【讨论】:

    • 这不排除轮班结束时间..否则可以..
    • @Rajesh 。 . .这在 CTE 中很容易调整。
    • 太棒了..您的解决方案也适用于我..谢谢..
    【解决方案2】:

    另一种非递归 CTE 方法可能是

    SQL> with test (time_from, time_to) as
      2    (select to_date('09.08.2020 07:00', 'dd.mm.yyyy hh24:mi'),
      3            to_date('09.08.2020 14:00', 'dd.mm.yyyy hh24:mi')
      4            from dual union all
      5     select to_date('09.08.2020 16:00', 'dd.mm.yyyy hh24:mi'),
      6            to_date('09.08.2020 18:00', 'dd.mm.yyyy hh24:mi')
      7            from dual
      8    )
      9  select time_from + ((column_value - 1) * 60) / (24 * 60) time
     10  from test cross join
     11    table(cast(multiset(select level from dual
     12                        connect by level <= (time_to - time_from) * 24
     13                       ) as sys.odcinumberlist));
    
    TIME
    ----------------
    09.08.2020 07:00
    09.08.2020 08:00
    09.08.2020 09:00
    09.08.2020 10:00
    09.08.2020 11:00
    09.08.2020 12:00
    09.08.2020 13:00
    09.08.2020 16:00
    09.08.2020 17:00
    
    9 rows selected.
    
    SQL>
    

    这些是带有时间的日期 - 您可以应用带有所需格式掩码的TO_CHAR 以根据需要显示它,例如

    select to_char(time_from + ((column_value - 1) * 60) / (24 * 60), 'hh:mi am') time
    

    导致

    TIME
    --------
    07:00 AM
    08:00 AM
    09:00 AM
    10:00 AM
    11:00 AM
    12:00 PM
    01:00 PM
    04:00 PM
    05:00 PM
    
    9 rows selected.
    

    如果要使用“分钟数”作为参数,则修改第 9 行和第 12 行:

    SQL> with test (time_from, time_to) as
      2    (select to_date('09.08.2020 07:00', 'dd.mm.yyyy hh24:mi'),
      3            to_date('09.08.2020 14:00', 'dd.mm.yyyy hh24:mi')
      4            from dual union all
      5     select to_date('09.08.2020 16:00', 'dd.mm.yyyy hh24:mi'),
      6            to_date('09.08.2020 18:00', 'dd.mm.yyyy hh24:mi')
      7            from dual
      8    )
      9  select to_char(time_from + ((column_value - 1) * &&par_minutes) / (24 * 60), 'hh:mi am') time
     10  from test cross join
     11    table(cast(multiset(select level from dual
     12                        connect by level <= (time_to - time_from) * 24 * (60 / &&par_minutes)
     13                       ) as sys.odcinumberlist));
    Enter value for par_minutes: 20
    old   9: select to_char(time_from + ((column_value - 1) * &&par_minutes) / (24 * 60), 'hh:mi am') time
    new   9: select to_char(time_from + ((column_value - 1) * 20) / (24 * 60), 'hh:mi am') time
    old  12:                       connect by level <= (time_to - time_from) * 24 * (60 / &&par_minutes)
    new  12:                       connect by level <= (time_to - time_from) * 24 * (60 / 20)
    
    TIME
    --------
    07:00 AM
    07:20 AM
    07:40 AM
    08:00 AM
    08:20 AM
    08:40 AM
    09:00 AM
    09:20 AM
    09:40 AM
    10:00 AM
    10:20 AM
    10:40 AM
    11:00 AM
    11:20 AM
    11:40 AM
    12:00 PM
    12:20 PM
    12:40 PM
    01:00 PM
    01:20 PM
    01:40 PM
    04:00 PM
    04:20 PM
    04:40 PM
    05:00 PM
    05:20 PM
    05:40 PM
    
    27 rows selected.
    
    SQL>
    

    【讨论】:

    • 这看起来不错..但是如果我想将持续时间从 60 分钟更改为任何其他值,比如 15 或 20 分钟。如何通过?
    • 我也添加了那个例子;看看吧。
    • 是的。成功了。这就是我想要的解决方案。非常感谢小脚先生
    • @Rajesh,如果这是您想要的解决方案,请接受答案并投票。这是正确表达感谢的方式;)
    • @RobertoHernandez 我试图投票。因为我是新成员,所以我不需要声望点来投票,这对每个人都是可见的..
    猜你喜欢
    • 2015-08-11
    • 2011-05-29
    • 1970-01-01
    • 1970-01-01
    • 2014-12-20
    • 1970-01-01
    • 2016-02-19
    • 2020-05-28
    • 1970-01-01
    相关资源
    最近更新 更多