选择具有和来自日期

时间:2017-11-08 05:51:42

标签: sql oracle

我正在制作一份报告,其中我想要一年中所有日子的日历,这些日历必须按顺序打印,即按日期排序。

我有两张桌子,一张有假期详情,另一张则有工作日的标准进出时间。

以下是两个表的列详细信息:

Working_hour_parameter Dt(Date),STD_INTIME ,STD_OUTTIME

假期from_dt, to_dt ,holiday_type, remarks

示例:如果我将日期范围从11月1日到11月5日,并且说第2次,11月3日是假日,则必须将结果返回为:

From date      To date      std_intime   std_outtime  remarks
-------        --------      --------   -------       ------ 
1st-Nov        1st-Nov      09:00        17:30        working day

2nd-Nov        3rd-Nov      (null)      (null)         holiday

4th-Nov        5th-Nov      09:00        17:30        working day

问题是,其中一个表有日期范围列,即日期和日期,另一个表是基于单个日期。

怎么可能?

有人可以帮帮我吗?

表格快照:

working hour parameter table

Holiday table

1 个答案:

答案 0 :(得分:0)

此问题的一般解决方案是为所需的每个日期生成一行,可以使用connect by rownum(特定于Oracle)或其他各种方法(如递归common table expression(许多dbs) )。如果您需要定期执行此操作,您甚至可能会考虑创建“日历表”。 e.g。

SELECT * from (
    SELECT to_date('2017-01-01','yyyy-mm-dd') + rownum - 1 dt
    FROM DUAL CONNECT BY ROWNUM < 366
    )
WHERE dt < to_date('2018-01-01','yyyy-mm-dd') 

在行中显示日期后,将两组数据连接到这些日期并完成作业。

select cal.dt, wp.*, h.*
from (
    SELECT to_date('2017-01-01','yyyy-mm-dd') + rownum - 1 dt
    FROM DUAL CONNECT BY ROWNUM < 36
     ) cal
left join Working_hour_parameter wp on cal.dt = wp.Dt
left join Holidays h on cal.dt between h.from_dt and h.to_dt 
WHERE cal.dt < to_date('2018-01-01','yyyy-mm-dd') 

----

为了提出一种总结每个数据的方法,first_value()和`last_value()用于形成“岛屿”以对范围进行分组。

可在SQL Fiddle

作为演示版提供
CREATE TABLE WORKING_HOUR_PARAMETER
    (DT timestamp, STD_INTIME varchar2(5), STD_OUTTIME varchar2(5))
;

INSERT ALL
    INTO WORKING_HOUR_PARAMETER ("DT", "STD_INTIME", "STD_OUTTIME")
         VALUES ('01-Jan-2017 12:00:00 AM', '09:00', '17:30')
    INTO WORKING_HOUR_PARAMETER ("DT", "STD_INTIME", "STD_OUTTIME")
         VALUES ('04-Jan-2017 12:00:00 AM', '09:00', '17:30')
    INTO WORKING_HOUR_PARAMETER ("DT", "STD_INTIME", "STD_OUTTIME")
         VALUES ('05-Jan-2017 12:00:00 AM', '09:00', '17:30')
    INTO WORKING_HOUR_PARAMETER ("DT", "STD_INTIME", "STD_OUTTIME")
         VALUES ('06-Jan-2017 12:00:00 AM', '09:00', '17:30')
SELECT * FROM dual
;

CREATE TABLE HOLIDAYS
    (FROM_DT timestamp, TO_DT timestamp, HOLIDAY_TYPE varchar2(8), REMARKS varchar2(12))
;

INSERT ALL 
    INTO HOLIDAYS ("FROM_DT", "TO_DT", "HOLIDAY_TYPE", "REMARKS")
         VALUES ('02-Jan-2017 12:00:00 AM', '03-Jan-2017 12:00:00 AM', 'whatever', 'avagoodbreak')
SELECT * FROM dual
;

查询1

select
         min(dt) span_from
       , max(dt) span_to
       , std_intime
       , std_outtime
       , from_dt hol_start
       , to_dt   hol_to
       , fval1   first_value
       , lval1   last_value
from (
    select cal.dt, h.FROM_DT, h.TO_DT, wp.std_intime, wp.std_outtime
    , first_value(FROM_DT ignore nulls) over(order by cal.dt rows between current row and unbounded following) fval1
    , last_value(TO_DT ignore nulls) over(order by cal.dt) lval1
    from (
        SELECT to_timestamp('2017-01-01','yyyy-mm-dd') + rownum - 1 dt
        FROM DUAL CONNECT BY ROWNUM < 36
         ) cal
    left join Working_hour_parameter wp on cal.dt = wp.Dt
    left join Holidays h on cal.dt between h.from_dt and h.to_dt 
    WHERE cal.dt < to_date('2017-01-07','yyyy-mm-dd') 
    )
group by
         std_intime
       , std_outtime
       , from_dt
       , to_dt
       , fval1
       , lval1
order by 1, 2

<强> Results

|            SPAN_FROM |              SPAN_TO | STD_INTIME | STD_OUTTIME |             HOL_START |                HOL_TO |           FIRST_VALUE |            LAST_VALUE |
|----------------------|----------------------|------------|-------------|-----------------------|-----------------------|-----------------------|-----------------------|
| 2017-01-01T00:00:00Z | 2017-01-01T00:00:00Z |      09:00 |       17:30 |                (null) |                (null) | 2017-01-02 00:00:00.0 |                (null) |
| 2017-01-02T00:00:00Z | 2017-01-03T00:00:00Z |     (null) |      (null) | 2017-01-02 00:00:00.0 | 2017-01-03 00:00:00.0 | 2017-01-02 00:00:00.0 | 2017-01-03 00:00:00.0 |
| 2017-01-04T00:00:00Z | 2017-01-06T00:00:00Z |      09:00 |       17:30 |                (null) |                (null) |                (null) | 2017-01-03 00:00:00.0 |