本月最后一个工作日的Oracle SQL,包括Oracle中的联邦假日

时间:2018-10-23 15:38:25

标签: sql oracle

我正在尝试查找Oracle SQL,以查找本月的最后一个工作日以及上个月的最后一个工作日。两种情况都应考虑联邦假日日历。

例如:

  • 本月最后一个营业日
  • 如果从2019年11月15日开始运行

从技术上讲,由于28日是感恩节假期,我应该在11月29日之前获得产出。

2 个答案:

答案 0 :(得分:3)

将这些联邦假日作为DATE类型存储在假日表中,然后 尝试执行以下操作:在该月的最后7天中找到最旧的(MAX)日,该日期既不是周六,周日,也不是 假期表。

这里的假设是:1)并非月底的所有7天都可以是假日或周末,以及2)星期六和星期日关闭。您可以根据上述假设是否始终成立来相应地调整level或where子句。

SELECT MAX(dt) AS last_working_day 
FROM
(
SELECT last_day(SYSDATE) - level + 1 as dt
FROM dual CONNECT BY
     level <= 7  -- the last seven days of the month
     )  WHERE TO_CHAR(dt,'DY', 'NLS_DATE_LANGUAGE = AMERICAN') NOT IN ('SAT','SUN')
     AND dt NOT IN ( SELECT holiday from federal_holidays );

一种更好的方法是拥有一个包含年中所有日期的日历表和一个名为isbusinessday的预定义列。这样查询就会简单得多。

SELECT MAX(dt)
  FROM calendar
  WHERE isbusinessday = 'Y' 
AND TO_CHAR(dt,'YYYYMM') = TO_CHAR(SYSDATE,'YYYYMM');

答案 1 :(得分:0)

拥有假期表通常可以正常工作,但是由于某些假期在移动,因此需要一些维护。例如,感恩节是11月的第4个星期四,即从11月22日到11月28日不等。

您还可以使用Oracle内置调度程序。通常,它用于控制OPTIONS,但我看不出为什么不应将其用于其他用途。

首先创建一个联邦假日列表,例如:

SCHEDULER JOBS

看看Calendaring Syntax,了解如何指定BEGIN DBMS_SCHEDULER.CREATE_SCHEDULE(schedule_name => 'CHRISTMAS', repeat_interval => 'FREQ=YEARLY;INTERVAL=1;BYDATE=1225', comments => 'December 25'); DBMS_SCHEDULER.CREATE_SCHEDULE(schedule_name => 'COLUMBUS_DAY', repeat_interval => 'FREQ=MONTHLY;BYMONTH=OCT;BYDAY=2 MON', comments => '2nd Monday in October'); DBMS_SCHEDULER.CREATE_SCHEDULE(schedule_name => 'INDEPENDENCE_DAY', repeat_interval => 'FREQ=YEARLY;INTERVAL=1;BYDATE=0704', comments => 'July 4'); DBMS_SCHEDULER.CREATE_SCHEDULE(schedule_name => 'MARTIN_LUTHER_KING_DAY', repeat_interval => 'FREQ=MONTHLY;BYMONTH=JAN;BYDAY=3 MON', comments => '3rd Monday in January'); DBMS_SCHEDULER.CREATE_SCHEDULE(schedule_name => 'MEMORIAL_DAY', repeat_interval => 'FREQ=MONTHLY;BYMONTH=MAY;BYDAY=-1 MON', comments => 'Last Monday of May'); DBMS_SCHEDULER.CREATE_SCHEDULE(schedule_name => 'NEW_YEARS_DAY', repeat_interval => 'FREQ=YEARLY;INTERVAL=1;BYDATE=0101', comments => 'January 1'); DBMS_SCHEDULER.CREATE_SCHEDULE(schedule_name => 'THANKSGIVING', repeat_interval => 'FREQ=MONTHLY;BYMONTH=NOV;BYDAY=4 THU', comments => '4th Thursday in November'); DBMS_SCHEDULER.CREATE_SCHEDULE(schedule_name => 'WASHINGTONS_BIRTHDAY', repeat_interval => 'FREQ=MONTHLY;BYMONTH=FEB;BYDAY=3 MON', comments => '3rd Monday in February'); DBMS_SCHEDULER.CREATE_SCHEDULE(schedule_name => 'WEEKEND', repeat_interval => 'FREQ=DAILY;INTERVAL=1;BYDAY=SAT,SUN'); -- Combined schedule for all federal holidays DBMS_SCHEDULER.CREATE_SCHEDULE(schedule_name => 'FEDERAL_HOLIDAYS', repeat_interval => 'FREQ=DAILY;INTERSECT=CHRISTMAS,INDEPENDENCE_DAY,MARTIN_LUTHER_KING_DAY,MEMORIAL_DAY,NEW_YEARS_DAY,THANKSGIVING,WASHINGTONS_BIRTHDAY'); END; /

然后,您可以使用过程repeat_interval来获取日期:

DBMS_SCHEDULER.EVALUATE_CALENDAR_STRING