我们已经在SQL中有一个函数计算第n个工作日期,不包括周末和假日,当你通过Startdate,Enddate和Workday(nth)时......它给你第n个工作日...
使用SQL函数:
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功能:
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;
答案 0 :(得分:1)
像这样的东西 - 在纯SQL中。如果你真的不需要使用PL / SQL,最好不要使用它。如果您确实需要使用它,请根据需要进行调整。我在评论中看到你已经改变了要求;根据需要进行调整。
&#34;幻数&#34; 2 * :wd_number + 5
用于确保我们添加足够的日历日期以包含至少:wd_number
个工作日; +5
适用于:wd_number
的低值。这不是最有效的解决方案,但它不会浪费超过几毫秒,所以我没有费心去提高效率。
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)
;
答案 1 :(得分:0)
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;
答案 2 :(得分:0)
------排除周末并计算第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 BY FIRST_DATE +(level-1)<= LAST_DATE ) TRIM(WORK_DAY)不在('SATURDAY','SUNDAY');