创建一个 SQL 函数,如果日期是假期,则 return

Creating a SQL Function that return if a date it's an holiday

我需要创建一个日历,在一行中显示一个月中的所有日期。 然后我需要显示同一个月的另一行,但要显示当天的第一个字母(M 代表星期一 - S 代表星期日等......)如果是假期日期则添加一个字母(C 代表民用,R 代表宗教) .

输出示例:

Date           Day
gennaio  2022, 1,  2, 3, 4, 5,  6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
gennaio  2022, Sr, D, L, M, M, Gr, V, S, D,  L,  M,  M,  G,  V,  S,  D,  L,  M,  M,  G,  V,  S,  D,  L,  M,  M,  G,  V,  S,  D,  L
febbraio 2022, 1,  2, 3, 4, 5,  6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, <null>, <null>, <null>
febbraio 2022, M,  M, G, V, S,  D, L, M, M,  G,  V,  S,  D,  L,  M,  M,  G,  V,  S,  D,  L,  M,  M,  G,  V,  S,  D,  L, <null>, <null>, <null>

我是用一个 table 和所有假期日期做的,然后从它到 return 做一个 select 如果那天是不是假期。

我想知道是否有可能以及如何创建一个 return 如果日期是否为假期而不需要额外的 table 的函数(我从 1 -01-2021 到 31-12-2025,意味着更早或更晚会出错)

我是意大利人,因为除复活节外所有假期都是固定的,我想函数只需要计算复活节日期,我就可以插入所有其他假期。

想法是通过函数从日期间隔(在我的例子中是从 1-01-2021 到 31-12-2025)执行 select,然后将其格式化为具有 2列如上所示,包含所有日期和节假日。

提前谢谢大家。

可以根据Gauss's Easter algorithm:

计算复活节
CREATE OR REPLACE FUNCTION Easter(yyyy IN INTEGER DEFAULT TO_CHAR(SYSDATE, 'YYYY')) RETURN DATE IS

    a INTEGER;
    b INTEGER;
    c INTEGER;
    d INTEGER;
    e INTEGER;
    f INTEGER;
    g INTEGER;
    h INTEGER;
    i INTEGER;
    k INTEGER;
    l INTEGER;
    m INTEGER;
    n INTEGER;
    p INTEGER;
    EM INTEGER;
    ED INTEGER;

BEGIN

    a := yyyy MOD 19;
    b := TRUNC(yyyy / 100);
    c := yyyy MOD 100;
    d := TRUNC(b / 4);
    e := b MOD 4;
    f := TRUNC((b + 8) / 25);
    g := TRUNC((b - f + 1) / 3);
    h := (19*a + b - d - g + 15) MOD 30;
    i := TRUNC(c / 4);
    k := c MOD 4;
    l := (32 + 2*e + 2*i - h - k) MOD 7;
    m := TRUNC((a + 11*h + 22*l) / 451);
    n := TRUNC((h + l - 7*m + 114) / 31);
    p := (h + l - 7*m + 114) MOD 31;
    EM := n;
    ed := p + 1;
    
    RETURN TO_DATE(yyyy||'-'||EM||'-'||ed, 'YYYY-MM-DD');
END Easter;

对于其他日子,你必须放一些简单的逻辑,例如

TO_CHAR(inputDate, 'MM-DD') = '12-25'

圣诞节。有些假期定义为“11 月的第 3 个星期一”,可能是这个:

TRUNC(inputDate) = NEXT_DAY(TRUNC(inputDate, 'MM')-1, 'MONDAY') + 2 * 7

简化示例:

CREATE OR REPLACE FUNCTION IsHoliday(d IN DATE) RETURN BOOLEAN IS
   easter DATE := Easter(TO_CHAR(d, 'YYYY'));
BEGIN

   IF TO_CHAR(d, 'Dy', 'NLS_DATE_LANGUAGE = "American"') IN ('Sat','Sun') THEN RETURN TRUE; -- Weekend
   IF TRUNC(d) = easter + 1 THEN RETURN TRUE; -- Easter Monday
   IF TO_CHAR(d, 'MM-DD') IN ('12-25', '12-26') THEN RETURN TRUE; -- Christmas
   IF TO_CHAR(d, 'MM-DD') = '05-01' THEN RETURN TRUE; -- Festa del Lavoro
   ... some more
   RETURN FALSE;

END IsHoliday;

另一种方法是 DBMS_SCHEDULER.EVALUATE_CALENDAR_STRING,例如:

DBMS_SCHEDULER.EVALUATE_CALENDAR_STRING(
   --Wednesday before November 23th 
   'FREQ=DAILY;BYDATE=1122-SPAN:7D;BYDAY=WED', 
   NULL, TRUNC(d, 'YYYY')-1, next_run_date);
IF TRUNC(d) = next_run_date THEN RETURN TRUE;