我正在尝试查找Oracle SQL,以查找本月的最后一个工作日以及上个月的最后一个工作日。两种情况都应考虑联邦假日日历。
例如:
从技术上讲,由于28日是感恩节假期,我应该在11月29日之前获得产出。
答案 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