使用Oracle Schedule获取下一个n个工作日
我想知道下一个工作日不包括周六、周日和节假日。我得到了如下错误的输出使用Oracle Schedule获取下一个n个工作日,oracle,oracle11g,Oracle,Oracle11g,我想知道下一个工作日不包括周六、周日和节假日。我得到了如下错误的输出 CREATE OR REPLACE FUNCTION FUNC_TO_GET_NEXT_BUSINESS_DAY( P_DATE IN DATE ,P_ADD_NUM IN INTEGER ) RETURN DATE AS -- V_CNT NUMBER; V_BUS_DAY DATE := TRUNC(P_DATE); -- BEGIN -- SELECT MAX(RNUM) INTO V_CNT F
CREATE OR REPLACE FUNCTION FUNC_TO_GET_NEXT_BUSINESS_DAY(
P_DATE IN DATE
,P_ADD_NUM IN INTEGER
) RETURN DATE AS
--
V_CNT NUMBER;
V_BUS_DAY DATE := TRUNC(P_DATE);
--
BEGIN
--
SELECT MAX(RNUM)
INTO V_CNT
FROM (SELECT ROWNUM RNUM
FROM ALL_OBJECTS)
WHERE ROWNUM <= P_ADD_NUM
AND TO_CHAR(V_BUS_DAY + RNUM, 'DY' ) NOT IN ('SAT', 'SUN')
AND NOT EXISTS
( SELECT 1
FROM HOLIDAY_LIST
WHERE HDLY_DATE = V_BUS_DAY + RNUM );
V_BUS_DAY := V_BUS_DAY + V_CNT;
--
RETURN V_BUS_DAY;
EXCEPTION
WHEN OTHERS THEN
Raise_application_error(-20010, SQLERRM);
--
END FUNC_TO_GET_NEXT_BUSINESS_DAY;
/
输出:
3/23/2076 3:00:00 PM
我会这样做:
CREATE OR REPLACE FUNCTION FUNC_TO_GET_NEXT_BUSINESS_DAY(
P_DATE IN DATE,
P_ADD_NUM IN INTEGER)
RETURN DATE AS
TYPE Date_list IS TABLE OF DATE;
Holidays Date_list;
res DATE := TRUNC(P_DATE) + P_ADD_NUM;
BEGIN
SELECT HDLY_DATE
BULK COLLECT INTO Holidays
WHERE HDLY_DATE >= res
FROM HOLIDAY_LIST;
LOOP
EXIT WHEN res NOT MEMBER OF Holidays AND TO_CHAR(res, 'DY', 'NLS_DATE_LANGUAGE = american') NOT IN ('SAT', 'SUN');
res := res + 1;
END LOOP;
RETURN res;
end;
我会这样做:
CREATE OR REPLACE FUNCTION FUNC_TO_GET_NEXT_BUSINESS_DAY(
P_DATE IN DATE,
P_ADD_NUM IN INTEGER)
RETURN DATE AS
TYPE Date_list IS TABLE OF DATE;
Holidays Date_list;
res DATE := TRUNC(P_DATE) + P_ADD_NUM;
BEGIN
SELECT HDLY_DATE
BULK COLLECT INTO Holidays
WHERE HDLY_DATE >= res
FROM HOLIDAY_LIST;
LOOP
EXIT WHEN res NOT MEMBER OF Holidays AND TO_CHAR(res, 'DY', 'NLS_DATE_LANGUAGE = american') NOT IN ('SAT', 'SUN');
res := res + 1;
END LOOP;
RETURN res;
end;
下面是我将如何编写本文,主要使用PL/SQL(最小化PL/SQL和SQL之间的上下文切换)。在Wernfried的解决方案中,我只需要将HOLIDAY_列表读入PL/SQL表,然后在PL/SQL中处理所有内容。与Wernfried的解决方案不同,此版本计算的日期为未来指定的业务天数,从输入日期开始计算
CREATE OR REPLACE FUNCTION FUNC_TO_GET_NEXT_BUSINESS_DAY (
P_DATE IN DATE ,
P_ADD_NUM IN INTEGER
) RETURN DATE AS
v_bus_day date := trunc(P_DATE);
cnt integer := P_ADD_NUM;
type date_list is table of date;
holidays date_list;
begin
select hdly_date
bulk collect into holidays
from holiday_list
where hdly_date > v_bus_day;
while cnt > 0
loop
v_bus_day := v_bus_day + 1;
if to_char(v_bus_day, 'DY') not in ('SAT', 'SUN')
and
v_bus_day not member of holidays
then cnt := cnt - 1;
end if;
end loop;
return v_bus_day;
end;
/
下面是我将如何编写本文,主要使用PL/SQL(最小化PL/SQL和SQL之间的上下文切换)。在Wernfried的解决方案中,我只需要将HOLIDAY_列表读入PL/SQL表,然后在PL/SQL中处理所有内容。与Wernfried的解决方案不同,此版本计算的日期为未来指定的业务天数,从输入日期开始计算
CREATE OR REPLACE FUNCTION FUNC_TO_GET_NEXT_BUSINESS_DAY (
P_DATE IN DATE ,
P_ADD_NUM IN INTEGER
) RETURN DATE AS
v_bus_day date := trunc(P_DATE);
cnt integer := P_ADD_NUM;
type date_list is table of date;
holidays date_list;
begin
select hdly_date
bulk collect into holidays
from holiday_list
where hdly_date > v_bus_day;
while cnt > 0
loop
v_bus_day := v_bus_day + 1;
if to_char(v_bus_day, 'DY') not in ('SAT', 'SUN')
and
v_bus_day not member of holidays
then cnt := cnt - 1;
end if;
end loop;
return v_bus_day;
end;
/
我在“批量收集”中使用上述函数时出错。逻辑似乎不正确。假设你想增加10天。您的函数在今天的基础上增加10天,如果不是周末或假日,则接受这一结果。从OP的解释和他的代码来看,他似乎希望从今天算起提前10个工作日,这是一个不同的概念。@mathguy,很可能是的,我没有详细研究他的代码。问题中没有说明。我认为标题中的“Get next n business days”表明了这一点。我在“BULK COLLECT”中使用上述函数时出错。逻辑似乎不正确。假设你想增加10天。您的函数在今天的基础上增加10天,如果不是周末或假日,则接受这一结果。从OP的解释和他的代码来看,他似乎希望从今天算起提前10个工作日,这是一个不同的概念。@mathguy,很可能是的,我没有详细研究他的代码。问题中没有说明。我认为标题中的“Get next n business days”表明了这一点。我只是编译了函数并用几个日期进行了测试,它正在生成正确的输出。不知道你为什么要在2076年约会。。。查看您的
假日列表
,确保其正确无误。另外,我看到您将一列命名为HDLY_DATE—这不应该是HLDY_DATE吗?几乎没有理由添加一个异常块,比如当其他块出现时。只要允许运行时抛出的任何异常通过内部机制引发就行了。我刚刚编译了该函数并用一些日期进行了测试,它正在生成正确的输出。不知道你为什么要在2076年约会。。。查看您的假日列表
,确保其正确无误。另外,我看到您将一列命名为HDLY_DATE—这不应该是HLDY_DATE吗?几乎没有理由添加一个异常块,比如当其他块出现时。只要允许运行时抛出的任何异常通过内部机制引发即可。为了独立于当前用户会话NLS设置,您应该将设置为\u CHAR(v\u bus\u day,'DY',NLS\u DATE\u LANGUAGE=american')而不是('SAT','SUN')
。@WernfriedDomscheit-对,但是,我们也必须考虑“周末”的定义(它不是所有国家的Sun Sun),等等。我通常试着不要“比教皇更虔诚”(在这些情况下是OP)。当然,这一点是很好的。你应该使<代码> toyChar(vButhayDay','Dy,'nLSsDATEAL =美国)不在(“SAT”,“Sun”)<代码>中,以独立于当前用户会话NLS设置。@ WnnFrReDeMeScEIT——对,但是我们还必须考虑“周末”(它不是所有国家的Sun Sun)的定义,等等。我一般都尽量不“比教皇更天主教”(在这些情况下,OP就是这样)。当然,这一点是正确的。