我试图找出下一个工作日排除SAT,SUN和Holidays。我得到错误的输出如下。
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;
/
INPUT:
select FUNC_TO_GET_NEXT_BUSINESS_DAY(sysdate,1)+15/24 from dual;
输出:
3/23/2076 3:00:00 PM
答案 0 :(得分:0)
我会这样做:
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;
答案 1 :(得分:0)
以下是我将如何编写此内容,主要使用PL / SQL(最小化PL / SQL和SQL之间的上下文切换)。在Wernfried的解决方案中,我只需要将HOLIDAY_LIST表读入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;
/