sql - 查找两个日期之间的第五个工作日sql
问题描述
我试图找到两个日期之间的第五个工作日,不包括假期。
这是我写的查询:
with s_date as (select TO_DATE('21-04-2020','DD-MM-YYYY') d from dual),
e_date as (select TO_DATE('01-05-2020','DD-MM-YYYY') d from dual),
no_of_days as (select abs(trunc(s_date.d - e_date.d))+1 no from s_date,e_date),
cal as (select d+rownum-1 dt
from s_date
connect by level <= (select no from no_of_days) )
select cal.dt from cal where to_char(cal.dt, 'DY', 'NLS_DATE_LANGUAGE=ENGLISH') NOT IN ('SAT', 'SUN')
and cal.dt not in (select day from T_PUBLIC_HOLIDAYS) order by cal.dt desc;
输出:
DT
1:30-04-2020
2:29-04-2020
3:28-04-2020
4:27-04-2020
5:24-04-2020
6:23-04-2020
7:22-04-2020
8:21-04-2020
如何将输出限制为仅:DT 1:24-04-2020
解决方案
这将在一个语句中计算多个开始日期和偏移日期的值:
甲骨文设置:
CREATE TABLE test_data ( start_date, days ) AS
SELECT DATE '2019-01-01' + date_offset, days
FROM ( SELECT LEVEL - 1 AS date_offset FROM DUAL CONNECT BY LEVEL <= 7 )
CROSS JOIN
( SELECT LEVEL - 1 AS days FROM DUAL CONNECT BY LEVEL <= 7 );
CREATE TABLE holidays ( holiday_date ) AS
SELECT DATE '2019-01-01' FROM DUAL UNION ALL
SELECT DATE '2019-01-09' FROM DUAL UNION ALL
SELECT DATE '2019-01-10' FROM DUAL;
创建一个辅助函数来添加工作日。这不是必需的,因为您可以将函数展开到查询中,但它使正在发生的事情变得更加明显:
CREATE FUNCTION add_weekdays(
start_date IN DATE,
weekdays IN NUMBER
) RETURN DATE DETERMINISTIC
IS
BEGIN
RETURN start_date
-- add full weeks
+ FLOOR( weekdays / 5 ) * 7
-- check to see if the remaining days go over a weekend, if so add 2 extra days
+ CASE WHEN ( start_date - TRUNC( start_date, 'IW' ) ) + MOD( weekdays, 5 ) >= 5
THEN MOD( weekdays, 5 ) + 2
ELSE MOD( weekdays, 5 )
END;
END;
/
查询:
WITH offsets ( start_date, days, offset_date, holiday_days ) AS (
SELECT start_date,
days,
add_weekdays( start_date, days ),
( SELECT COUNT(*)
FROM holidays
WHERE holiday_date BETWEEN start_date
AND add_weekdays( start_date, days )
)
FROM test_data
UNION ALL
-- recurse and add the previously found holiday days and look to see if any more holidays overlap
SELECT start_date,
days,
add_weekdays( offset_date, holiday_days ),
( SELECT COUNT(*)
FROM holidays
WHERE holiday_date BETWEEN offset_date + 1
AND add_weekdays( offset_date, holiday_days )
)
FROM offsets
-- stop recursing when no holiday days are found
WHERE holiday_days > 0
)
CYCLE start_date, days, offset_date SET is_cycle TO 1 DEFAULT 0
SELECT TO_CHAR( start_date, 'DY YYYY-MM-DD' ) AS start_dt,
days,
TO_CHAR( offset_date, 'DY YYYY-MM-DD' ) AS offset_dt,
( offset_date - start_date ) - days AS skipped_days
FROM offsets
WHERE holiday_days = 0
ORDER BY start_date, days;
输出:
(考试节假日为2019-01-01
,跳过天数包括节假日和周末2019-01-09
)2019-01-10
START_DT | 天 | OFFSET_DT | SKIPPED_DAYS :------------- | ---: | :------------- | ------------: 周二 2019-01-01 | 0 | 周三 2019-01-02 | 1 周二 2019-01-01 | 1 | 星期四 2019-01-03 | 1 周二 2019-01-01 | 2 | 周五 2019-01-04 | 1 周二 2019-01-01 | 3 | 星期一 2019-01-07 | 3 周二 2019-01-01 | 4 | 周二 2019-01-08 | 3 周二 2019-01-01 | 5 | 周五 2019-01-11 | 5 周二 2019-01-01 | 6 | 星期一 2019-01-14 | 7 周三 2019-01-02 | 0 | 周三 2019-01-02 | 0 周三 2019-01-02 | 1 | 星期四 2019-01-03 | 0 周三 2019-01-02 | 2 | 周五 2019-01-04 | 0 周三 2019-01-02 | 3 | 星期一 2019-01-07 | 2 周三 2019-01-02 | 4 | 周二 2019-01-08 | 2 周三 2019-01-02 | 5 | 周五 2019-01-11 | 4 周三 2019-01-02 | 6 | 星期一 2019-01-14 | 6 星期四 2019-01-03 | 0 | 星期四 2019-01-03 | 0 星期四 2019-01-03 | 1 | 周五 2019-01-04 | 0 星期四 2019-01-03 | 2 | 星期一 2019-01-07 | 2 星期四 2019-01-03 | 3 | 周二 2019-01-08 | 2 星期四 2019-01-03 | 4 | 周五 2019-01-11 | 4 星期四 2019-01-03 | 5 | 星期一 2019-01-14 | 6 星期四 2019-01-03 | 6 | 周二 2019-01-15 | 6 周五 2019-01-04 | 0 | 周五 2019-01-04 | 0 周五 2019-01-04 | 1 | 星期一 2019-01-07 | 2 周五 2019-01-04 | 2 | 周二 2019-01-08 | 2 周五 2019-01-04 | 3 | 周五 2019-01-11 | 4 周五 2019-01-04 | 4 | 星期一 2019-01-14 | 6 周五 2019-01-04 | 5 | 周二 2019-01-15 | 6 周五 2019-01-04 | 6 | 周三 2019-01-16 | 6 SAT 2019-01-05 | 0 | 星期一 2019-01-07 | 2 SAT 2019-01-05 | 1 | 周二 2019-01-08 | 2 SAT 2019-01-05 | 2 | 周五 2019-01-11 | 4 SAT 2019-01-05 | 3 | 星期一 2019-01-14 | 6 SAT 2019-01-05 | 4 | 周二 2019-01-15 | 6 SAT 2019-01-05 | 5 | 周三 2019-01-16 | 6 SAT 2019-01-05 | 6 | 周四 2019-01-17 | 6 孙 2019-01-06 | 0 | 周二 2019-01-08 | 2 孙 2019-01-06 | 1 | 周五 2019-01-11 | 4 孙 2019-01-06 | 2 | 星期一 2019-01-14 | 6 孙 2019-01-06 | 3 | 周二 2019-01-15 | 6 孙 2019-01-06 | 4 | 周三 2019-01-16 | 6 孙 2019-01-06 | 5 | 周四 2019-01-17 | 6 孙 2019-01-06 | 6 | 周五 2019-01-18 | 6 星期一 2019-01-07 | 0 | 星期一 2019-01-07 | 0 星期一 2019-01-07 | 1 | 周二 2019-01-08 | 0 星期一 2019-01-07 | 2 | 周五 2019-01-11 | 2 星期一 2019-01-07 | 3 | 星期一 2019-01-14 | 4 星期一 2019-01-07 | 4 | 周二 2019-01-15 | 4 星期一 2019-01-07 | 5 | 周三 2019-01-16 | 4 星期一 2019-01-07 | 6 | 周四 2019-01-17 | 4
db<>在这里摆弄
推荐阅读
- sql - 如何在sql中重新排序跳过的数字
- typescript - 如何在Angular 7中的POST方法中捕获响应
- php - 我正在使用 PHP Laravel 5.8 创建编辑页面。我已经创建了路由和 url,但出现错误 404 not found
- python - 如何让精灵随机生成?
- c# - 从继承自 AuthorizationHandler 的类访问 ViewBag
- c# - WPF中插件的样式模板
- ios - Swift - 如何在不迭代领域对象集合的情况下批量更新对象
- ios - 项目选择需要在vue js多选中点击IOS两次
- android - 如何在 RecyclerView 中获取适配器位置
- amazon-web-services - AWS JS SDK V3(Lambda 模块)- 无法连接到实例元数据服务