我编写了一个函数(Oracle SQL),它根据不同国家/地区的日历计算两个日期之间的工作日数。它需要运行数千次,因此速度非常重要。 您输入一个开始日期,结束日期和给定日历的名称,例如“US”,“UK”等。输入参数在不同的SQL中传递,但是现在我还在测试。 该功能使用假期表来查找日期之间的非工作日。该表包含不同国家的所有周末和国家法定假日。问题是尽管使用了游标,但功能很慢。有没有提示,如何使功能更快?我怀疑函数中的select查询是问题所在。我可能错了,但我不知道该怎么办。
CREATE OR REPLACE FUNCTION Test (in_dt1 DATE,
in_dt2 DATE,
in_Calender VARCHAR)
RETURN NUMBER
IS
Count_days NUMBER := 0;
beg_dt DATE;
End_dt DATE;
Curr_dt DATE;
Cursor_dato DATE;
CURSOR C1
IS
SELECT b.holiday
FROM calendars a
INNER JOIN holidays b ON a.calik = b.calik
WHERE a.cal = in_Calender AND holiday >= in_dt1 AND holiday <= in_dt2;
BEGIN
OPEN c1;
beg_dt := LEAST (in_dt1, in_dt2);
End_dt := GREATEST (in_dt1, in_dt2);
Curr_dt := beg_dt + 1;
<<OUTER>>
WHILE Curr_dt <= End_dt
LOOP
FETCH c1 INTO cursor_dato;
WHILE cursor_dato IS NULL
LOOP
Count_days := Count_days + 1;
Curr_dt := Curr_dt + 1;
EXIT OUTER WHEN Curr_dt = End_dt + 1;
END LOOP;
WHILE Curr_dt < cursor_dato
LOOP
Count_days := Count_days + 1;
Curr_dt := Curr_dt + 1;
EXIT OUTER WHEN Curr_dt = End_dt;
END LOOP;
IF Curr_dt > cursor_dato
THEN
Count_days := Count_days + 1;
END IF;
Curr_dt := Curr_dt + 1;
END LOOP;
CLOSE c1;
RETURN Count_days;
END;
答案 0 :(得分:5)
select trunc (end_dt) - trunc(beg_dt) from dual;
给出两个日期之间的天数。
select count(1) from holidays where holiday >= beg_dt AND holiday <= end_dt;
给出两个日期之间的假期数。
第一 - 秒给你结果。没有游标,循环等。
类似于:
CREATE OR REPLACE FUNCTION Test (in_dt1 DATE,
in_dt2 DATE,
in_Calender VARCHAR2,
p_country varchar2)
RETURN NUMBER
IS
Count_days NUMBER := 0;
beg_dt DATE;
End_dt DATE;
count_holidays number := 0;
begin
beg_dt := LEAST (in_dt1, in_dt2);
End_dt := GREATEST (in_dt1, in_dt2);
count_days := trunc(end_dt) - trunc(beg_dt);
select count(1)
into count_holidays
from holidays
where holiday >= beg_dt
AND holiday <= end_dt
and country = p_country;
return Count_days - count_holidays;
end;
我已添加国家参数来计算正确的假期。