我有下面的游标:
OPEN p_results FOR
SELECT distinct S02.CONVERSATION_ID, S02.INTERNAL_USI, S02.PRN, S02.CRN,
S01.EARLIEST_B_DATE "Bank Date", S01.EARLIEST_B_NARRATIVE||'DSEC' "BN",
abs(S01.TOTAL_B_AMOUNT - S02.TOTAL_C_AMOUNT) "GA",
decode(S01.EXTRA_FLAG_4,1,'OP',2,'UP') "Batch Status",
(case
when S01.latest_b_date > S02.latest_c_date then S01.latest_b_date
else S02.latest_c_date
end ) Effective_Date, S02.ICC_ID,
S02.MATCH_METHOD,
S01.TOTAL_B_AMOUNT
FROM TTPAY S01,
TTCONT S02
Where S01.EXTRA_FLAG_4 in (1,2)
and S02.EXTRA_FLAG_4 in (1,2)
and S01.Match_no = 0
and S02.Match_no = 0
and S01.PRN = S02.PRN;
对于这段代码,我必须进行以下更改:如果以下结果中的生效日期是假日或周末,那么我需要添加+1,而星期六需要+2,否则我将使用结果在下面的代码中以有效日期返回。
(case
when S01.latest_b_date > S02.latest_c_date then S01.latest_b_date
else S02.latest_c_date
end ) Effective_Date
我有一个名为WORKING_DAY
的函数,该函数以一个日期作为参数,并在检查假期日历和周末后返回布尔值,分别为TRUE
或FALSE
。
如何在上面的代码片段中有效使用该功能以获取所需的日期?
答案 0 :(得分:0)
我有一个名为
WORKING_DAY
的函数,该函数以一个日期作为参数,并在检查假期日历和周末后返回布尔值,分别为TRUE
或FALSE
。如何在上面的代码片段中有效使用该功能以获取所需的日期?
您不能在SQL语句中使用它,因为BOOLEAN
是PL/SQL data type,并且在SQL中不存在。
如果要在SQL中返回真实值,则返回文字(即0
/ 1
或'Y'
/ 'N'
等),并进行比较,如果您需要。
因此,您应将函数从将BOOLEAN
(仅PL / SQL)数据类型返回为:
CREATE FUNCTION is_working_day(
dt IN DATE
) RETURN NUMBER
IS
is_working_day BOOLEAN;
BEGIN
-- do stuff.
IF is_working_day THEN
RETURN 1;
ELSE
RETURN 0;
END IF;
END;
/
更新
更改功能后,如何在该代码段中使用该功能以获取所需的有效日期?
您不能使用该功能来确定需要添加多少天。该函数返回真实值,因此,除非您要连续第二天进行迭代并测试是否为工作日(在SQL中很难做到),否则您当前的返回真实值的方法将无效。
相反,将逻辑移到一个函数中,该函数会告诉您要添加多少天:
CREATE FUNCTION days_until_next_working_day(
dt IN DATE
) RETURN INTEGER
IS
current_day DATE := dt;
BEGIN
WHILE NOT is_working_day( current_day ) LOOP
current_day := current_day + INTERVAL '1' DAY;
END LOOP;
RETURN current_day - dt;
END;
/
(可能有一种更有效的方式来编写此代码,以计算下一个工作日,而不是在每个连续的工作日中进行迭代,但是我们不知道您如何确定假期等,因此我们可以对其进行优化。)
然后只需将返回值添加到您的SQL查询中即可跳过这几天。
答案 1 :(得分:0)
在这种情况下,您拥有的功能几乎没有用。您必须知道有效日期是否为
因此,如果它返回TRUE或FALSE,则无法对其进行任何操作。您需要一个新函数,该函数将返回VARCHAR2
,例如sun
或sat
或hol
或null
(代表一个工作日)。然后,您可以在编写的查询中使用它。怎么样?一种简单的方法-无需使用触摸代码即可-将其用作嵌入式视图:
OPEN p_results FOR
SELECT conversation_id,
CASE --> this is where you decide
WHEN working_day_vc (effective_date) = 'sat' --> whether day is SAT/SUN/HOLIDAY
THEN
effective_date + 2
WHEN working_day_vc (effective_date) IN ('sun', 'hol')
THEN
effective_date + 1
ELSE
effective_date
END
effective_date
FROM (
-- this is your current query
SELECT DISTINCT
S02.CONVERSATION_ID,
S02.INTERNAL_USI,
S02.PRN,
S02.CRN,
S01.EARLIEST_B_DATE "Bank Date",
S01.EARLIEST_B_NARRATIVE || 'DSEC' "BN",
ABS (S01.TOTAL_B_AMOUNT - S02.TOTAL_C_AMOUNT) "GA",
DECODE (S01.EXTRA_FLAG_4, 1, 'OP', 2, 'UP')
"Batch Status",
(CASE
WHEN S01.latest_b_date > S02.latest_c_date
THEN
S01.latest_b_date
ELSE
S02.latest_c_date
END)
Effective_Date,
S02.ICC_ID,
S02.MATCH_METHOD,
S01.TOTAL_B_AMOUNT
FROM TTPAY S01, TTCONT S02
WHERE S01.EXTRA_FLAG_4 IN (1, 2)
AND S02.EXTRA_FLAG_4 IN (1, 2)
AND S01.Match_no = 0
AND S02.Match_no = 0
AND S01.PRN = S02.PRN);
答案 2 :(得分:0)
如果这是某种报告,并且在sql中执行。例如
with
function wf_WORKING_DAY(p_Date date) return number is
begin
return case when WORKING_DAY(p_Date) then 1 else 0 end;
end;
select wf_WORKING_DAY(date'2020-01-01')
from dual
/
答案 3 :(得分:0)
非常感谢@MT0 在这方面的帮助。
我写在下面以减轻要求。
CREATE OR REPLACE PACKAGE ACTUAL_DATE
IS
FUNCTION IS_WORKING_DAY (IN_DATE IN DATE) RETURN BOOLEAN;
FUNCTION DAYS_UNTIL_NEXT_WORKING_DAY(IN_DATE IN DATE) RETURN NUMBER;
FUNCTION GET_NEXT_BUSINESS_DAY(IN_DATE IN DATE) RETURN DATE;
END ACTUAL_DATE;
/
CREATE OR REPLACE PACKAGE BODY ACTUAL_DATE
IS
FUNCTION IS_WORKING_DAY (IN_DATE DATE) RETURN BOOLEAN
IS
HOLIDAYCOUNTER NUMBER :=0;
DAYNUM POSITIVE;
BEGIN
-- CHECK DATE AGAINST NTBS_HOLIDAYS TABLE
HOLIDAYCOUNTER :=0;
SELECT COUNT(*) INTO HOLIDAYCOUNTER
FROM HOLIDAY_CALENDAR
WHERE HOLIDAY_DATE = TO_DATE(IN_DATE);
-- DETERMINE IF A WEEKDAY
DAYNUM := TO_CHAR( IN_DATE, 'd');
-- RETURN TRUE (1) ONLY IF A WEEKDAY AND NOT A NSW PPUBLIC HOLIDAY
IF DAYNUM BETWEEN 2 AND 6 AND HOLIDAYCOUNTER = 0 THEN
RETURN TRUE;
ELSE
RETURN FALSE;
END IF;
END IS_WORKING_DAY;
-- DETERMINE NO. OF DAYS TO ACHIEVE NEXT WORK DAY FOR GIVEN DATE
FUNCTION DAYS_UNTIL_NEXT_WORKING_DAY(
IN_DATE IN DATE
) RETURN NUMBER
IS
CURRENT_DAY DATE := IN_DATE;
NUMBERS_OF_DAY NUMBER;
BEGIN
WHILE NOT IS_WORKING_DAY( CURRENT_DAY ) LOOP
CURRENT_DAY := CURRENT_DAY + INTERVAL '1' DAY;
END LOOP;
NUMBERS_OF_DAY := CURRENT_DAY - IN_DATE;
RETURN NUMBERS_OF_DAY;
END;
-- ADD NO.OF DAYS TO GIVEN DATE TO GET ACTUAL EFFECTIVE DATE
FUNCTION GET_NEXT_BUSINESS_DAY(IN_DATE IN DATE) RETURN DATE
IS
BUSINESSDAY DATE := IN_DATE;
ACTUAL_BUSINESSDAY DATE;
BEGIN
IF (IN_DATE IS NULL)
THEN
RAISE_APPLICATION_ERROR
(
-20999,
'null date passed to get_next_business_day'
);
END IF;
ACTUAL_BUSINESSDAY := BUSINESSDAY + DAYS_UNTIL_NEXT_WORKING_DAY(IN_DATE);
RETURN ACTUAL_BUSINESSDAY;
END;
END ACTUAL_DATE;
/
答案 4 :(得分:0)
通过简化假设,您可以将此过程简化为单个查询。该假设是您可以定义最大连续关闭天数。根据这个假设,当给定一个营业日期时,您会生成一个可能的下一个营业日期列表,然后从该列表中选择并返回未包含在假期表中的最短日期。我选择了 14 天作为最大连续关闭天数。虽然查询本身并不过分复杂,但也不是很简单,因此我会将它隐藏在一个函数中。见domo。
create or replace
function next_business_day( current_business_date_in date
, max_consecutive_days_closed_in integer default 14
)
return date
as
l_next_business_day date;
begin
with day_list (possible_next_date) as
-- generate list of possible next business days within
-- the defined consecutive days closed
(select possible_next_date
from (select current_business_date_in + level possible_next_date
from dual
connect by level < max_consecutive_days_closed_in
)
where to_char(possible_next_date,'d') not in ('6','7')
)
-- next business date is the minimum date from the list
-- that is not in the holiday table.
select min(possible_next_date)
into l_next_business_day
from day_list
where possible_next_date not in
(select holiday_date
from holidays
union all
-- make sure there is a last holiday defined
select date '9999-12-31' from dual
);
return l_next_business_day;
end next_business_day;
要使用,如果我正确理解您的查询,只需将您的 case 语句替换为对该函数的调用。所以
(CASE
WHEN S01.latest_b_date > S02.latest_c_date
THEN
S01.latest_b_date
ELSE
S02.latest_c_date
END) Effective_Date,
变成
next_business_day(S01.latest_b_date) Effective_Date,
注意:刚刚注意到这实际上是一个旧帖子,但我最初看到的是昨天。所以我想我会离开它。