Get nth working date in Oracle
我们已经在SQL中提供了一个函数,当您传递Startdate,Enddate和Workday(nth)时,它会计算第n个工作日(不包括周末和节假日)。它为您提供第n个工作日...
正在运行的SQL函数:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | FUNCTION [dbo].[getNthWorkingDate] ( @StartDate AS datetime, @EndDate AS datetime, @WorkDay AS int ) RETURNS datetime AS BEGIN -- Declare the return variable here DECLARE @WorkDate AS datetime, @LeaveYear AS SMALLINT,@iCount AS int SET @LeaveYear = datepart(YEAR, @StartDate) SET @iCount = 1 WHILE (@StartDate < @EndDate) BEGIN IF (DATENAME(WEEKDAY,@StartDate ) = 'SUNDAY') OR (DATENAME(WEEKDAY,@StartDate ) = 'SATURDAY') -- Just to keep the if statement with out code SET @iCount = @iCount; ELSE IF EXISTS (SELECT * FROM HOLIDAYS WHERE CAST (HOLIDAY + ' ' + CAST(@LeaveYear AS VARCHAR) AS DATETIME) = @StartDate) -- Just to keep the if statement with out code SET @iCount = @iCount; ELSE BEGIN SET @WorkDate = @StartDate IF @iCount = @WorkDay BREAK; ELSE SET @iCount = @iCount + 1; END SET @StartDate = dateadd(DAY, 1, @StartDate ); END -- Return the result of the function RETURN @WorkDate END |
我正在尝试在ORACLE(oracle的新手)中重新创建此函数,我进行了一些更改,但无法正常工作,我认为我在循环中缺少某些内容,将不胜感激...在此先感谢..
ORACLE功能:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | CREATE OR REPLACE FUNCTION GETNTHWORKINGDATE (pStartDate DATE, pEndDate DATE, pWorkDay NUMBER) RETURN DATE AS vStartDate DATE; vWorkDate DATE ; vCount NUMBER; vHoliday DATE; BEGIN vCount := 1; BEGIN SELECT HOLIDAY_DATE INTO vHoliday FROM HOLIDAY WHERE (TO_CHAR(HOLIDAY_DATE, 'MM DD') = TO_CHAR(pStartDate, 'MM DD')); EXCEPTION WHEN NO_DATA_FOUND THEN vHoliday := NULL; END; vStartDate := pStartDate; BEGIN WHILE (vStartDate < pEndDate) LOOP IF (TO_CHAR(vStartDate, 'DAY') = 'SUNDAY' ) OR (TO_CHAR(vStartDate, 'DAY') = 'SATURDAY') THEN vCount := vCount; ELSIF (TO_CHAR(vHoliday, 'MM DD') = TO_CHAR(vStartDate, 'MM DD')) THEN vCount := vCount; ELSE vWorkDate := vStartDate; IF vCount = pWorkDay THEN EXIT; ELSE vCount := vCount + 1; END IF; END IF; vStartDate := vStartDate + 1; END LOOP; END; RETURN vWorkDate; END GETNTHWORKINGDATE; |
类似的事情适用-在普通SQL中。如果您真的不需要使用PL / SQL,最好不要使用它。如果确实需要使用它,请根据需要进行调整。我在评论中看到您已经更改了需求;根据需要进行调整。
"魔术数字"
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | WITH holidays( holiday_date, holiday_name ) AS ( SELECT DATE '2016-01-01', 'New Year''s Day' FROM dual UNION ALL SELECT DATE '2016-04-01', 'April Fools'' Day' FROM dual UNION ALL SELECT DATE '2016-05-01', 'May First' FROM dual ), work_days ( dt ) AS ( SELECT TO_DATE(:start_date, 'yyyy-mm-dd') + LEVEL - 1 FROM dual WHERE TO_CHAR(TO_DATE(:start_date, 'yyyy-mm-dd') + LEVEL - 1, 'Dy') NOT IN ('Sat', 'Sun') CONNECT BY LEVEL < 2 * TO_NUMBER(:wd_number) + 5 MINUS SELECT holiday_date FROM holidays ), ordered_work_days ( dt, rn ) AS ( SELECT dt, ROW_NUMBER() over (ORDER BY dt) FROM work_days ) SELECT dt FROM ordered_work_days WHERE rn = TO_NUMBER(:wd_number) ; |
------排除周末并计算第N个工作日
选择--CURRENTDATE
WORK_DATE,
WORK_DAY,
ROW_NUMBER()已于NTH_WORKING_DAY(在WORK_DATE之前订购)
从
(
-按日期获取所有日期
选择货币,
FIRST_DATE(级别-1),截至WORK_DATE,
TO_CHAR(FIRST_DATE(LEVEL-1),'DAY')AS WORK_DAY
从
(
-获取每月的当前日期,第一个日期和最后一个日期
SELECT sysdate CURRENTDATE,
TRUNC(sysdate,'MM')AS FIRST_DATE,
LAST_DAY(sysdate)LAST_DATE
从双重
)
CONNECT FIRST_DATE(级别-1)<= LAST_DATE
)
TRIM(WORK_DAY)不在('SATURDAY','SUNDAY');
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | CREATE OR REPLACE FUNCTION GETNTHWORKINGDATE (pStartDate DATE, pEndDate DATE, pWorkDay NUMBER) RETURN DATE AS vStartDate DATE; vWorkDate DATE ; vCount NUMBER; vHoliday DATE; BEGIN vCount := 1; vStartDate := pStartDate; BEGIN WHILE (vStartDate < pEndDate) LOOP BEGIN --Select Holiday Month and Date into vHoliday Variable when Start Date is a holiday. SELECT HOLIDAY_DATE INTO vHoliday FROM HOLIDAY WHERE (TO_CHAR(HOLIDAY_DATE, 'MM DD') = TO_CHAR(vStartDate, 'MM DD')); EXCEPTION WHEN NO_DATA_FOUND THEN vHoliday := NULL; END; -- Code to eliminate Weekends IF (TO_CHAR(vStartDate, 'D') = 1 ) OR (TO_CHAR(vStartDate, 'D') = 7) THEN vCount := vCount; --Code to eliminate Holiday's from holiday table. ELSIF (TO_CHAR(vHoliday, 'MM DD') = TO_CHAR(vStartDate, 'MM DD')) THEN vCount := vCount; ELSE vWorkDate := vStartDate; IF vCount = pWorkDay THEN EXIT; ELSE vCount := vCount + 1; END IF; END IF; vStartDate := vStartDate + 1; END LOOP; END; RETURN vWorkDate; END GETNTHWORKINGDATE; |