【问题标题】:Generate dates and hours from range with filter使用过滤器从范围内生成日期和时间
【发布时间】:2019-04-04 19:13:02
【问题描述】:

它所在的源表:

ID   Date_Start   Date_End     DayOfWeek   Time_Start  Time_End   field1
1    01/02/2018   15/02/2018   4           08:00:00    10:00:00   text1
2    01/06/2018   15/06/2018   2           10:00:00    13:00:00   text1

第 4 天代表星期四,因此我只想生成 DayOfWeek 的日期和时间(源表中的 (4)Thursday 和 (2)Tuesday)。

我想得到这个输出:

Date        hour     field1
01/02/2018  08       text1
01/02/2018  09       text1
01/02/2018  10       text1
08/02/2018  08       text1
08/02/2018  09       text1
08/02/2018  10       text1
15/02/2018  08       text1
15/02/2018  09       text1
15/02/2018  10       text1
05/06/2018  10       text1
05/06/2018  11       text1
05/06/2018  12       text1
05/06/2018  13       text1
12/06/2018  10       text1
12/06/2018  11       text1
12/06/2018  12       text1
12/06/2018  13       text1

我尝试编辑此good answer,使用 *24 来获取小时数但没办法!

谢谢。

【问题讨论】:

    标签: sql oracle oracle11g


    【解决方案1】:

    这是一个示例,说明如何执行链接文章答案显示的操作。请注意,Oracle 没有time 类型,只有datetimes,所以我不确定您是如何存储时间的。出于此答案的目的,我只是将它们附加到开始/结束日期。

    WITH test_data AS (
        SELECT 1 AS ID, 
               to_date('01/02/2018','dd/mm/yyyy') AS date_start,
               to_date('15/02/2018','dd/mm/yyyy') AS date_end,
               4 AS dayOfWeek,
               to_date('08:00:00','hh24:mi:ss') AS time_start,
               to_date('10:00:00','hh24:mi:ss') AS time_end,
               'text1' AS field1
        FROM dual
    
        UNION
    
        SELECT 2 AS ID, 
               to_date('01/06/2018','dd/mm/yyyy') AS date_start,
               to_date('15/06/2018','dd/mm/yyyy') AS date_end,
               2 AS dayOfWeek,
               to_date('10:00:00','hh24:mi:ss') AS time_start,
               to_date('13:00:00','hh24:mi:ss') AS time_end,
               'text1' AS field1
        FROM dual
    ), all_hours_in_range AS (
        SELECT d.id, 
               LEVEL, 
               d.date_start, 
               d.date_end, 
               d.date_start + (LEVEL - 1) / 24 AS new_date, 
               d.dayOfWeek, 
               d.time_start,
               d.time_end,
               d.field1
        FROM test_data d
        CONNECT BY LEVEL <= (date_end - date_start) * 24 + 1
          AND PRIOR ID = ID
          AND PRIOR sys_guid() IS NOT NULL
    )
    
    SELECT to_char(a.new_date, 'dd/mm/yyyy') AS new_date, 
           to_char(a.new_date, 'hh24') AS new_hour, 
           a.field1
    FROM all_hours_in_range a
    WHERE to_char(a.new_date, 'hh24') >= to_char(a.time_start, 'hh24') /* Filter to results that are within specified hours */
      AND to_char(a.new_date, 'hh24') <= to_char(a.time_end, 'hh24') 
      AND 1 + TRUNC (a.new_date) - TRUNC (a.new_date, 'IW') = a.dayOfWeek /* Filter to results that are on specified day of week */
    

    【讨论】:

    • 感谢您的回答,但您忘记了工作时间
    • @KiMaN 正如我所说,您需要指定存储时间的方式。 Oracle 没有时间数据类型,只有日期时间。
    • 小时存储在日期列(Time_Start 和 Time_End)中,我用 to_char 函数显示它们。
    • 必须在同一字段中合并 date_start 和 time_start 才能使过滤器正常工作,因为日期列中的时间部分与时间字段不同。并将 new_date 字段增加 1 小时。您允许我更新您的答案,或者您更愿意自己做@JoshEller?
    【解决方案2】:

    另一种选择:

    SQL> with test (id, date_start, date_end, dayofweek, time_start, time_end, field1) as
      2    (select 1, '01/02/2018', '15/02/2018', 4, '08:00:00', '10:00:00', 'text1' from dual union all
      3     select 2, '01/06/2018', '15/06/2018', 2, '10:00:00', '13:00:00', 'text2' from dual
      4    ),
      5  inter as
      6    (select id, dayofweek, field1, time_start, time_end,
      7            to_date(date_start || time_start, 'dd/mm/yyyyhh24:mi:ss') pstart,
      8            to_date(date_start || time_end,   'dd/mm/yyyyhh24:mi:ss') pend,
      9            to_date(date_end,                 'dd/mm/yyyy') kend
     10     from test
     11    ),
     12  inter2 as
     13    (select i.id,
     14         i.pstart + (t1.column_value - 1)/24 dt,
     15         i.dayofweek,
     16         i.field1,
     17         i.time_start,
     18         i.time_end
     19     From inter i,
     20       table(cast(multiset(select level from dual
     21                           connect by level <= ((kend - pstart) + 1) * 24
     22                          ) as sys.odcinumberlist)) t1
     23    )
     24  select to_char(dt, 'dd/mm/yyyy') cdate,
     25         to_char(dt, 'hh24') chour,
     26         field1
     27  from inter2
     28  where to_char(dt, 'd') = dayofweek
     29    and to_char(dt, 'hh24') between substr(time_start, 1, 2) and substr(time_end, 1, 2);
    
    CDATE      CH FIELD
    ---------- -- -----
    01/02/2018 08 text1
    01/02/2018 09 text1
    01/02/2018 10 text1
    08/02/2018 08 text1
    08/02/2018 09 text1
    08/02/2018 10 text1
    15/02/2018 08 text1
    15/02/2018 09 text1
    15/02/2018 10 text1
    05/06/2018 10 text2
    05/06/2018 11 text2
    05/06/2018 12 text2
    05/06/2018 13 text2
    12/06/2018 10 text2
    12/06/2018 11 text2
    12/06/2018 12 text2
    12/06/2018 13 text2
    
    17 rows selected.
    
    SQL>
    

    【讨论】:

      猜你喜欢
      • 2015-04-10
      • 1970-01-01
      • 2020-12-20
      • 2018-06-17
      • 2015-05-23
      • 2017-10-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多