使用过滤器从范围生成日期和小时

时间:2019-04-04 19:13:03

标签: sql oracle oracle11g

下面的源表:

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来获取时间,但没有办法!

谢谢。

2 个答案:

答案 0 :(得分: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 */

答案 1 :(得分:1)

另一个选择:

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>