我正在制作一份报告,其中我想要一年中所有日子的日历,这些日历必须按顺序打印,即按日期排序。
我有两张桌子,一张有假期详情,另一张则有工作日的标准进出时间。
以下是两个表的列详细信息:
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
问题是,其中一个表有日期范围列,即日期和日期,另一个表是基于单个日期。
怎么可能?
有人可以帮帮我吗?
表格快照:
答案 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()用于形成“岛屿”以对范围进行分组。
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 |