雪花数据模拟的复活节/耶稣受难日

Easter / Good Friday for Sowflake Date Dim

进一步发展:下面的代码满足了早期评论中的要求[如果你关注历史]:),我下面的新问题让我很困惑。

问题:我想'Week_Of_Year'每周日调整,下面的代码每周一执行。我已经尝试过 1 和 0,但是通过 alter session per雪花,但没有运气!知道如何让星期日而不是星期一触发新的一周吗(目前是这样)?

即我想要的结果是 Date:1/2/2005 将 Week_Of_Year 反映为 2,而不是 1。 改变会话集 week_of_year_policy = 1; 对比 改变会话集 week_of_year_policy = 0;
工作代码

create or replace temporary table test_temptable 
  ( 
   DATE_ID                 SMALLINT               NOT NULL
  ,FULL_DATE               DATE                   NOT NULL
  ,DATE                    Varchar(10)            NOT NULL
  ,YEAR                    SMALLINT               NOT NULL
  ,WEEK_OF_YEAR            SMALLINT               NOT NULL
  ,DAY_OF_YEAR             SMALLINT               NOT NULL
  ,QTR_NUMBER              SMALLINT               NOT NULL
  ,DAY_OF_QUARTER          SMALLINT               NOT NULL 
  ,MONTH_OF_YEAR           SMALLINT               NOT NULL
  ,MONTH_NAME              CHAR(3)                NOT NULL --need to have full month name, if it comes to it maybe do if logic
  ,DAY_OF_MONTH            SMALLINT               NOT NULL
  ,DAY_OF_WEEK             VARCHAR(9)             NOT NULL
  ,DAY_NAME                VARCHAR(12)            NOT NULL
  ,DAY_IS_WEEKDAY          boolean                NOT Null 
  ,DAY_IS_LAST_OF_MONTH    boolean                NOT Null
  ,DAY_OF_WEEK_IN_MONTH    SMALLINT               NOT NULL
  ,HOLIDAYUSA              VARCHAR(80)                       ----left out NOT NULL on Purpose
 --- ,DAY_IS_HOLIDAY          boolean                NOT NULL 

)
AS
    WITH MY_DATES AS (
    SELECT DATEADD(DAY, SEQ4(), '2005-01-01') AS Full_DATE 
    ,(seq8()+ 1) AS date_id
    ,DATE_TRUNC('QUARTER',Full_DATE) as Q
    ,DATEDIFF('day',Q, Full_DATE) as Day_of_Quarter
     /*logic to support Easter Day calculation */
    ,Full_DATE as SinCurDay
    ,MONTH(Full_Date) as inCurMonth
    ,YEAR(Full_Date) as inCurYear
    ,FLOOR(inCurYear/100) as inCurCent
    ,inCurYear%19 as inYear
    ,FLOOR((inCurCent-17)/25) as inYearTmp
    ,(inCurCent-FLOOR(inCurCent/4)-FLOOR((inCurCent-inYearTmp)/3)+(19*inYear)+15)%30 as inTemp2a
    ,inTemp2a-FLOOR(inTemp2a/28)*(1 - FLOOR(inTemp2a/28)*FLOOR(29/(inTemp2a+1))*FLOOR((21-inYear)/11)) as inTemp2b
    ,(inCurYear+FLOOR(inCurYear/4)+inTemp2b+2-inCurCent+FLOOR(inCurCent/4))%7 as inTemp3
    ,inTemp2b-inTemp3 as inTemp4
    ,3+FLOOR((inTemp4+40)/44) as inEastMontha
    ,inTemp4+28-31*FLOOR(inEastMontha/4) as inEastDay
    ,inEastMontha /*- 1*/ as inEastMonthb 
    ,Date_from_parts(inCurYear,inEastMonthb, inEastDay) as EasterDay
    /*End Easter Day Logic */

     /*Day of Week in Month*/
     /* CASE
            WHEN Day(Full_Date) < 8 THEN 1
            WHEN Day(Full_Date) BETWEEN 7 AND 14 then 2
            WHEN Day(Full_Date) BETWEEN 14 AND 21 then 3
            WHEN Day(Full_Date) BETWEEN 21 AND 28 then 4 
            ELSE 5 End as Day_In_Month
      */

      FROM TABLE(GENERATOR(ROWCOUNT=>365))  
  )
  SELECT date_id
        ,Full_Date
        ,to_varchar(Full_Date, 'mm/dd/yyyy')
        ,YEAR(Full_Date)
        ,WEEKOFYEAR(Full_Date) 
        ,DAYOFYEAR(Full_Date)
        ,QUARTER(Full_Date)
        ,Day_Of_Quarter + 1
        ,MONTH(Full_Date)
        ,MONTHNAME(Full_Date)
        ,DAY(Full_Date)
        ,DAYOFWEEK(Full_Date) + 1
        ,DAYNAME(Full_Date)
        /*Weekend boolean */
        ,CASE 
            WHEN DAYOFWEEK(Full_date) + 1 = 7 THEN FALSE
            WHEN DAYOFWEEK(Full_date) + 1 = 1 THEN FALSE
         ELSE TRUE END
        /*Last Day Of Month Boolean*/
        ,CASE 
            WHEN Full_Date = last_day(Full_Date) THEN True 
         ELSE FALSE END
       /*Week in Month*/
       ---,CAST(Round((day(Full_Date) +6)/7,0) as VARCHAR)
       ,CASE
            WHEN Day(Full_Date) < 8 THEN 1
            WHEN Day(Full_Date) BETWEEN 7 AND 14 then 2
            WHEN Day(Full_Date) BETWEEN 14 AND 21 then 3
            WHEN Day(Full_Date) BETWEEN 21 AND 28 then 4 
            ELSE 5 End

       /*HolidayUSA Logic */
       ,CASE 
            WHEN MONTH(Full_Date) = 10 AND DAY(Full_Date) = 31 THEN 'Halloween'
            /*ThanksGiving*/
            WHEN MONTH(Full_Date) = 11 AND DAYOFWEEK(Full_Date) + 1 = 5 AND 
                CASE 
                    WHEN Day(Full_Date) < 8 THEN 1
                    WHEN Day(Full_Date) BETWEEN 7 AND 14 then 2
                    WHEN Day(Full_Date) BETWEEN 14 AND 21 then 3
                    WHEN Day(Full_Date) BETWEEN 21 AND 28 then 4 
                ELSE 5 End = 4 
            THEN 'Thanksgiving Day' -- should I add ()

            WHEN MONTH(Full_Date) = 11 AND DAYOFWEEK(Full_Date) + 1 = 6 AND 
                CASE 
                    WHEN Day(Full_Date) < 8 THEN 1
                    WHEN Day(Full_Date) BETWEEN 7 AND 14 then 2
                    WHEN Day(Full_Date) BETWEEN 14 AND 21 then 3
                    WHEN Day(Full_Date) BETWEEN 21 AND 28 then 4 
                ELSE 5 End = 4 
            THEN 'Black Friday' -- should I add ()



            WHEN MONTH(Full_Date) = 12 AND DAY(Full_Date) = 25 THEN 'Christmas Day'
            WHEN MONTH(Full_Date) = 7 AND DAY(Full_Date) = 4 THEN 'Independence Day'
            WHEN MONTH(Full_Date) = 12 AND DAY(Full_Date) = 31 THEN 'New Years Eve'
            WHEN MONTH(Full_Date) = 1 AND DAY(Full_Date) = 1 THEN 'New Years Day'
            WHEN MONTH(Full_Date) = 5 AND DAYOFWEEK(Full_Date)+ 1 = 2 AND Day(Full_Date) > '24' then 'Memorial Day'
            WHEN MONTH(Full_Date) = 9 AND DAYOFWEEK(Full_Date) + 1 = 2 AND Day(Full_Date) < '8'THEN 'Labor Day'

            /*Martin Luther King Jr Day */
            WHEN MONTH(Full_Date) = 1 AND DAYOFWEEK(Full_Date) + 1 = 2 AND 
            CASE 
                    WHEN Day(Full_Date) < 8 THEN 1
                    WHEN Day(Full_Date) BETWEEN 7 AND 14 then 2
                    WHEN Day(Full_Date) BETWEEN 14 AND 21 then 3
                    WHEN Day(Full_Date) BETWEEN 21 AND 28 then 4 
                ELSE 5 End 
             = 3 THEN 'Martin Luther King Jr Day'


            /*Presidents Day*/
            WHEN MONTH(Full_Date) = 2 AND DAYOFWEEK(Full_Date) + 1 = 2 AND
            CASE 
                    WHEN Day(Full_Date) < 8 THEN 1
                    WHEN Day(Full_Date) BETWEEN 7 AND 14 then 2
                    WHEN Day(Full_Date) BETWEEN 14 AND 21 then 3
                    WHEN Day(Full_Date) BETWEEN 21 AND 28 then 4 
                ELSE 5 END
            = 3  THEN 'Presidents Day'






            WHEN MONTH(Full_Date) = 11 AND DAY(Full_Date) = 11 THEN 'Veterans Day' 


            /*Mothers Day */

            WHEN MONTH(Full_Date) = 5 AND DAYOFWEEK(Full_Date) + 1 = 1 AND
            CASE 
                    WHEN Day(Full_Date) < 8 THEN 1
                    WHEN Day(Full_Date) BETWEEN 7 AND 14 then 2
                    WHEN Day(Full_Date) BETWEEN 14 AND 21 then 3
                    WHEN Day(Full_Date) BETWEEN 21 AND 28 then 4 
                ELSE 5 END
            =  2 THEN 'Mothers Day'

            /*Fathers Day */
            WHEN MONTH(Full_Date) = 6 AND DAYOFWEEK(Full_Date) + 1 = 1 AND
            CASE 
                    WHEN Day(Full_Date) < 8 THEN 1
                    WHEN Day(Full_Date) BETWEEN 7 AND 14 then 2
                    WHEN Day(Full_Date) BETWEEN 14 AND 21 then 3
                    WHEN Day(Full_Date) BETWEEN 21 AND 28 then 4 
                ELSE 5 END
            = 3  THEN 'Fathers Day'




            WHEN MONTH(Full_Date) = 2 AND DAY(Full_Date) = 14 THEN 'Valentines Day'
            WHEN Full_Date = EasterDay THEN 'Easter Day'
            WHEN Full_Date = EasterDay - 2 THEN 'Good Friday'
        ELSE NULL END
      --- ,CASE
      ---      WHEN HOLIDAYUSA is not NULL THEN TRUE Else False
     ---   END

    FROM MY_DATES
    Order By Full_Date;

进化的问题:请查看更新的代码,我在其中将 T-SQL 逻辑转换为 Snowflake 可以理解的计算复活节的内容。唯一的问题是 2005 年我休假一天(return 下面的代码是 2005 年 3 月 28 日复活节,但现在是 2008 年 3 月 27 日)。

问题:有人能帮我理解为什么下面的行如此接近但错误吗,我已经尝试了很多 rtrim、RIGHT 和其他操作来处理输入日期的值,认为它与四舍五入有关下降,但所有这些都使 return 复活节日期更远。下面是我最近的 20 年跨度,都在实际的 1-5 天内。

导致错误的行:date_from_parts(YR, '0' + rtrim(EasterMonth),'0' + rtrim(EasterDay)) AS test6

复活节逻辑

(24 + 19 * (YR % 19)) % 30 AS EpactCalc, 
        EpactCalc - (EpactCalc / 28) AS PaschalDaysCalc, 
        PaschalDaysCalc - ((YR + YR / 4 + PaschalDaysCalc - 13) % 7) AS NumOfDaysToSunday, 
        3 + (NumOfDaysToSunday + 40) / 44 AS EasterMonth, 
        NumOfDaysToSunday + 28 - (31 * (EasterMonth / 4)) AS EasterDay, ---EasterMonth + RTRIM(YR) as test6
        ---to_date_from_parts(YR,(("0" + EasterMonth).substr(-2)), (("0" + EasterDay).substr(-2)) as test6
        date_from_parts(YR, '0' + rtrim(EasterMonth),'0' + rtrim(EasterDay)) AS test6

完整脚本:

CREATE OR REPLACE
TEMPORARY TABLE .test_temptable (Date_Id SMALLINT NOT NULL ,Full_Date DATE NOT NULL ,Date Varchar(10) NOT NULL ,YEAR SMALLINT NOT NULL ,WEEK_OF_YEAR SMALLINT NOT NULL ,DAY_OF_YEAR SMALLINT NOT NULL ,QTR_Number SMALLINT NOT NULL ,Day_Of_Quarter SMALLINT NOT NULL,MONTH_OF_YEAR SMALLINT NOT NULL ,MONTH_NAME CHAR(3) NOT NULL --need to have full month name, if it comes to it maybe do if logic
 ,DAY_OF_MONTH SMALLINT NOT NULL ,DAY_OF_WEEK VARCHAR(9) NOT NULL ,DAY_NAME VARCHAR(12) NOT NULL ,DAY_IS_WEEKDAY boolean NOT NULL,DAY_IS_LAST_OF_MONTH boolean NOT NULL ,DAY_OF_WEEK_IN_MONTH SMALLINT NOT NULL ,HOLIDAYUSA VARCHAR(80) ----left out NOT NULL on Purpose
 ,test1 smallint NOT NULL,test2 smallint NOT NULL ,test3 smallint NOT NULL ,test4 smallint NOT NULL,test5 smallint NOT NULL ,test6 DATE NOT NULL) AS WITH CTE_MY_DATE AS
  (---Returns a sequence of monotonically increasing integers, with wrap-around. Wrap-around occurs after the largest representable integer of the integer width (1, 2, 4, or 8 byte)..??I'd like to understand this a tad bit better.Is SEQ4 for float?
 SELECT DATEADD(DAY, SEQ4(), '2005-01-01') AS Full_DATE, 
        YEAR(Full_Date) AS YR, 
        (seq8()+ 1) AS date_id, 
        DATE_TRUNC('QUARTER',Full_DATE) AS q, 
        DATEDIFF('day',q, Full_DATE) AS Day_of_Quarter, 
        (24 + 19 * (YR % 19)) % 30 AS EpactCalc, 
        EpactCalc - (EpactCalc / 28) AS PaschalDaysCalc, 
        PaschalDaysCalc - ((YR + YR / 4 + PaschalDaysCalc - 13) % 7) AS NumOfDaysToSunday, 
        3 + (NumOfDaysToSunday + 40) / 44 AS EasterMonth, 
        NumOfDaysToSunday + 28 - (31 * (EasterMonth / 4)) AS EasterDay, ---EasterMonth + RTRIM(YR) as test6
        ---to_date_from_parts(YR,(("0" + EasterMonth).substr(-2)), (("0" + EasterDay).substr(-2)) as test6
        date_from_parts(YR, '0' + rtrim(EasterMonth),'0' + rtrim(EasterDay)) AS test6 


   FROM TABLE(GENERATOR(ROWCOUNT=>9125)) 
 ) 
SELECT date_id ,
       Full_Date ,
       to_varchar(Full_Date, 'mm/dd/yyyy') ,
       YEAR(Full_Date) ,
       WEEKOFYEAR(Full_Date) ,
       DAYOFYEAR(Full_Date) ,
       QUARTER(Full_Date) ,
       Day_Of_Quarter + 1 ,
       MONTH(Full_Date) ,
       MONTHNAME(Full_Date) ,
       DAY(Full_Date) ,
       DAYOFWEEK(Full_Date) + 1 ,
       DAYNAME(Full_Date) ---calculates if it is on weekend or not
 ,
       CASE 
           WHEN DAYOFWEEK(Full_date) = 7 THEN FALSE 
           WHEN DAYOFWEEK(Full_date) = 1 THEN FALSE 
           ELSE TRUE 
       END ----calculates if last day of month 
 ,
       CASE 
           WHEN Full_Date = last_day(Full_Date) THEN TRUE 
           ELSE FALSE 
       END,
       CAST(Round((day(Full_Date) +6)/7,0) AS VARCHAR) -- this is what week you are in in the month, double check that what it ought to be 
 --- calculates holidays, is Thxgiving always in the fifth week?, 
 ,
       CASE 
           WHEN MONTH(Full_Date) = 10
                AND DAY(Full_Date) = 31 THEN 'Halloween' 
           WHEN MONTH(Full_Date) = 11
                AND DAYOFWEEK(Full_Date) + 1 = 4
                AND CAST(Round((day(Full_Date) +6)/7,0) AS VARCHAR) = 5 THEN 'Thanksgiving Day' 
           WHEN MONTH(Full_Date) = 12
                AND DAY(Full_Date) = 25 THEN 'Christmas Day' 
           WHEN MONTH(Full_Date) = 7
                AND DAY(Full_Date) = 4 THEN 'Independence Day' --adding

           WHEN MONTH(Full_Date) = 12
                AND DAY(Full_Date) = 31 THEN 'New Years Eve' 
           WHEN MONTH(Full_Date) = 1
                AND DAY(Full_Date) = 1 THEN 'New Years Day' ---memorial day attempt

           WHEN MONTH(Full_Date) = 5
                AND DAYOFWEEK(Full_Date)+ 1 = 2
                AND Day(Full_Date) > '24' THEN 'Memorial Day' ---labor day

           WHEN MONTH(Full_Date) = 9
                AND DAYOFWEEK(Full_Date) + 1 = 2
                AND Day(Full_Date) < '8'THEN 'Labor Day' 
           WHEN MONTH(Full_Date) = 1
                AND DAYOFWEEK(Full_Date) = 2
                AND CAST(Round((day(Full_Date) +6)/7,0) AS VARCHAR) = 3 THEN 'Martin Luther King Jr Day' 
           WHEN MONTH(Full_Date) = 2
                AND DAYOFWEEK(Full_Date) = 2
                AND CAST(Round((day(Full_Date) +6)/7,0) AS VARCHAR) = 3 THEN 'Presidents Day' 
           WHEN MONTH(Full_Date) = 11
                AND DAY(Full_Date) = 11 THEN 'Veterans Day' ---added Mother's Day

           WHEN MONTH(Full_Date) = 5
                AND DAYOFWEEK(Full_Date) + 1 = 1
                AND CAST(Round((day(Full_Date) +6)/7,0) AS VARCHAR) = 2 THEN 'Mothers Day'
           WHEN MONTH(Full_Date) = 6
                AND DAYOFWEEK(Full_Date) + 1 = 1
                AND CAST(Round((day(Full_Date) +6)/7,0) AS VARCHAR) = 3 THEN 'Fathers Day'
           WHEN MONTH(Full_Date) = 2
                AND DAY(Full_Date) = 14 THEN 'Valentines Day' ---easter
 ---good friday

           ELSE NULL
       END ,
       EpactCalc ,
       PaschalDaysCalc ,
       NumOfDaysToSunday ,
       EasterMonth ,
       EasterDay ,
       test6
FROM CTE_MY_DATE;

老问题: 我为 snowflake 用户准备了一段不错的代码,需要一些帮助才能完成。我特别想使用为 SqlServer 编写的第二段代码用于 Snowflakes env,并集成到我下面的脚本中(第一段代码)。

具体来说: a)"How do you integrate a function into a query like this" 就像上面建议将代码放在我的脚本中的位置一样,因为我无法理解如何在 select 语句中集成函数 b)"Is there anything glaring about this query that would make running it in Snowflake uniquely difficult" 我试图 运行 SQL 服务器 "easter date" 代码单独在雪花中,并更改变量以匹配雪花要求(即去掉@)然后我得到了错误 unexpected 'BEGIN'.

    CREATE OR REPLACE
TEMPORARY TABLE test_temptable (Date_Id SMALLINT NOT NULL ,Full_Date DATE NOT NULL ,Date Varchar(10) NOT NULL ,YEAR SMALLINT NOT NULL ,WEEK_OF_YEAR SMALLINT NOT NULL ,DAY_OF_YEAR SMALLINT NOT NULL ,QTR_Number SMALLINT NOT NULL ,Day_Of_Quarter SMALLINT NOT NULL,MONTH_OF_YEAR SMALLINT NOT NULL ,MONTH_NAME CHAR(3) NOT NULL 
 ,DAY_OF_MONTH SMALLINT NOT NULL ,DAY_OF_WEEK VARCHAR(9) NOT NULL ,DAY_NAME VARCHAR(12) NOT NULL ,DAY_IS_WEEKDAY boolean NOT NULL,DAY_IS_LAST_OF_MONTH boolean NOT NULL ,DAY_OF_WEEK_IN_MONTH SMALLINT NOT NULL ,HOLIDAYUSA VARCHAR(80) 
  (
 SELECT DATEADD(DAY, SEQ4(), '2005-01-01') AS Full_DATE, 
        (seq8()+ 1) AS date_id, 
        DATE_TRUNC('QUARTER',Full_DATE) AS q, 
        DATEDIFF('day',q, Full_DATE) AS Day_of_Quarter

   FROM TABLE(GENERATOR(ROWCOUNT=>366)) 
 ) 
SELECT date_id ,
       Full_Date ,
       to_varchar(Full_Date, 'mm/dd/yyyy') ,
       YEAR(Full_Date) ,
       WEEKOFYEAR(Full_Date) ,
       DAYOFYEAR(Full_Date) ,
       QUARTER(Full_Date) ,
       Day_Of_Quarter + 1 ,
       MONTH(Full_Date) ,
       MONTHNAME(Full_Date) ,
       DAY(Full_Date) ,
       DAYOFWEEK(Full_Date) + 1 ,
       DAYNAME(Full_Date)
 ,
       CASE 
           WHEN DAYOFWEEK(Full_date) = 7 THEN FALSE 
           WHEN DAYOFWEEK(Full_date) = 1 THEN FALSE 
           ELSE TRUE 
       END 
 ,
       CASE 
           WHEN Full_Date = last_day(Full_Date) THEN TRUE 
           ELSE FALSE 
       END,
       CAST(Round((day(Full_Date) +6)/7,0) AS VARCHAR) 
 ,
       CASE 
           WHEN MONTH(Full_Date) = 10
                AND DAY(Full_Date) = 31 THEN 'Halloween' 
           WHEN MONTH(Full_Date) = 11
                AND DAYOFWEEK(Full_Date) + 1 = 4
                AND CAST(Round((day(Full_Date) +6)/7,0) AS VARCHAR) = 5 THEN 'Thanksgiving Day' 
           WHEN MONTH(Full_Date) = 12
                AND DAY(Full_Date) = 25 THEN 'Christmas Day' 
           WHEN MONTH(Full_Date) = 7
                AND DAY(Full_Date) = 4 THEN 'Independence Day' --adding

           WHEN MONTH(Full_Date) = 12
                AND DAY(Full_Date) = 31 THEN 'New Years Eve' 
           WHEN MONTH(Full_Date) = 1
                AND DAY(Full_Date) = 1 THEN 'New Years Day' ---memorial day attempt

           WHEN MONTH(Full_Date) = 5
                AND DAYOFWEEK(Full_Date)+ 1 = 2
                AND Day(Full_Date) > '24' THEN 'Memorial Day' ---labor day

           WHEN MONTH(Full_Date) = 9
                AND DAYOFWEEK(Full_Date) + 1 = 2
                AND Day(Full_Date) < '8'THEN 'Labor Day' 
           WHEN MONTH(Full_Date) = 1
                AND DAYOFWEEK(Full_Date) = 2
                AND CAST(Round((day(Full_Date) +6)/7,0) AS VARCHAR) = 3 THEN 'Martin Luther King Jr Day' 
           WHEN MONTH(Full_Date) = 2
                AND DAYOFWEEK(Full_Date) = 2
                AND CAST(Round((day(Full_Date) +6)/7,0) AS VARCHAR) = 3 THEN 'Presidents Day' 
           WHEN MONTH(Full_Date) = 11
                AND DAY(Full_Date) = 11 THEN 'Veterans Day' ---added Mother's Day

           WHEN MONTH(Full_Date) = 5
                AND DAYOFWEEK(Full_Date) + 1 = 1
                AND CAST(Round((day(Full_Date) +6)/7,0) AS VARCHAR) = 2 THEN 'Mothers Day'
           WHEN MONTH(Full_Date) = 6
                AND DAYOFWEEK(Full_Date) + 1 = 1
                AND CAST(Round((day(Full_Date) +6)/7,0) AS VARCHAR) = 3 THEN 'Fathers Day'
           WHEN MONTH(Full_Date) = 2
                AND DAY(Full_Date) = 14 THEN 'Valentines Day' ---easter
 ---good friday

           ELSE NULL
       END
FROM CTE_MY_DATE;

下面是SQL服务器代码 我需要帮助输入上面的内容!! (感谢Function to return date of Easter for the given year

    CREATE FUNCTION dbo.GetEasterSunday 
( @Y INT ) 
RETURNS SMALLDATETIME 
AS 
BEGIN 
    DECLARE     @EpactCalc INT,  
        @PaschalDaysCalc INT, 
        @NumOfDaysToSunday INT, 
        @EasterMonth INT, 
        @EasterDay INT 

    SET @EpactCalc = (24 + 19 * (@Y % 19)) % 30 
    SET @PaschalDaysCalc = @EpactCalc - (@EpactCalc / 28) 
    SET @NumOfDaysToSunday = @PaschalDaysCalc - ( 
        (@Y + @Y / 4 + @PaschalDaysCalc - 13) % 7 
    ) 

    SET @EasterMonth = 3 + (@NumOfDaysToSunday + 40) / 44 

    SET @EasterDay = @NumOfDaysToSunday + 28 - ( 
        31 * (@EasterMonth / 4) 
    ) 

    RETURN 
    ( 
        SELECT CONVERT 
        (  SMALLDATETIME, 
                 RTRIM(@Y)  
            + RIGHT('0'+RTRIM(@EasterMonth), 2)  
            + RIGHT('0'+RTRIM(@EasterDay), 2)  
        ) 
    ) 

END 
GO

新答案: 您必须直接使用月份和日期数值,而不是重新格式化为 TEXT:

DATE_FROM_PARTS(Year, EasterMonth, EasterDay)

旧答案:
将 T-SQL 函数转换为 Snowflake JavaScript 函数应该相当简单。
不过,也许你必须在途中学习 JavaScript。

这样一个函数的骨架可以是:

CREATE OR REPLACE FUNCTION GetEasterSunday(Y FLOAT) RETURNS STRING LANGUAGE JAVASCRIPT AS
$$
  var EpactCalc = (24 + 19 * (Y % 19)) % 30;
  // more stuff here
  var EasterMonth = 4, EasterDay = 21;
  return Y + "-" + ("0" + EasterMonth).substr(-2) + "-" + ("0" + EasterDay).substr(-2);
$$;
SELECT GetEasterSunday(2019)::DATE; 

当您使用整数时,T-SQL 似乎会截断值。它根本不考虑小数部分。

在 T-SQL 中是这样的:

select -2 + 28 - (31 * (3 / 4)) as [EasterDay]

Returns: 26

在雪花中

select -2 + 28 - (31 * (3 / 4)) as [EasterDay]

Returns: 2.75

但是如果你截断值 3 / 4 = 0.75 ,它给出相同的 T-SQL (因为如果你省略小数部分它是 trunc(0.75)=0:

select -2 + 28 - (31 * trunc(3 / 4)) as [EasterDay]

Returns: 26

所以在 T-SQL 中是这样的:

WITH years as(
    SELECT   2009 AS [Year]
    UNION ALL
    SELECT   yl.[Year] + 1 AS [Year]
    FROM     years yl
    WHERE    yl.[Year] + 1 <= YEAR(dateadd(year,5,GETDATE()))
), 
e AS 
(
 SELECT d.[Year], [EasterDate] = CONVERT(DATE, RTRIM([Year]) + '0' + RTRIM([Month]) 
        + RIGHT('0' + RTRIM([Day]),2))
      FROM (SELECT [Year],[Month], [Day] = DaysToSunday + 28 - (31 * ([Month] / 4))
      FROM (SELECT [Year],[Month] = 3 + (DaysToSunday + 40) / 44, DaysToSunday
      FROM (SELECT [Year],DaysToSunday = paschal - (([Year] + [Year] / 4 + paschal - 13) % 7 )
      FROM (SELECT [Year],paschal = epact - (epact / 28)
      FROM (SELECT years.[Year], epact = (24 + 19 * (years.[Year] % 19)) % 30 from years)  AS epact) AS paschal) AS dts) AS m) AS d
  )
  select *
  from(
  SELECT [Year],[EasterDate], HolidayName = 'Easter Sunday' FROM e
    UNION ALL SELECT [Year],DATEADD(DAY,-2,[EasterDate]), 'Good Friday'   FROM e
    UNION ALL SELECT [Year],DATEADD(DAY, 1,[EasterDate]), 'Easter Monday' FROM e
    UNION ALL SELECT [Year],DATEADD(DAY, 39,[EasterDate]), 'Ascension Day' FROM e --NOTE! 1973–1991 this was moved to always to previous saturday!
    UNION ALL SELECT [Year],DATEADD(DAY, 49,[EasterDate]), 'Whit Sunday' FROM e --NOTE! 7th sunday from Easter Sunday
  ) easter
  order by easter.[Year],[EasterDate]

像这样在雪花中

WITH years as(
    --select distinct "YearNumber" as "Year" FROM dm.D_DAY
    select year(dateadd(year, seq4(), dateadd(year,-13,current_date()))) as "Year"
    from
    table(generator(rowcount => 19))
), 
e AS 
(
 SELECT "EasterYear","EasterMonth", "EasterDay","DaysToSunday","epact","paschal",
      DATE_FROM_PARTS("EasterYear", "EasterMonth", "EasterDay") as "EasterDate"
      FROM (SELECT "EasterYear","epact","paschal","EasterMonth" AS "EasterMonth","DaysToSunday", "DaysToSunday" + 28 - (31 * trunc("EasterMonth" / 4)) as "EasterDay"
      FROM (SELECT "EasterYear","epact","paschal",trunc(3 + ("DaysToSunday" + 40) / 44,0) as "EasterMonth", "DaysToSunday" 
      FROM (SELECT "EasterYear","epact","paschal","paschal" - trunc(mod(("EasterYear" + "EasterYear" / 4 + "paschal" - 13),7 )) as "DaysToSunday" 
      FROM (SELECT "EasterYear","epact","epact" - trunc("epact" / 28) as "paschal"
      FROM (SELECT years."Year" as "EasterYear", mod((24 + (19 * mod(years."Year",19))),30) as "epact" from years)  AS "epact") AS "paschal") AS "dts") AS "m") AS d
 )
  select *
  from(       SELECT "EasterYear","EasterDate",'Easter Sunday' as "HolidayName" FROM e
    UNION ALL SELECT "EasterYear",DATEADD(DAY,-2,"EasterDate"), 'Good Friday'       FROM e
    UNION ALL SELECT "EasterYear",DATEADD(DAY, 1,"EasterDate"), 'Easter Monday'     FROM e
    UNION ALL SELECT "EasterYear",DATEADD(DAY, 39,"EasterDate"), 'Ascension Day'    FROM e --NOTE! 1973–1991 this was moved to always to previous saturday!
    UNION ALL SELECT "EasterYear",DATEADD(DAY, 49,"EasterDate"), 'Whit Sunday'      FROM e --NOTE! 7th sunday from Easter Sunday
  ) easter
  order by easter."EasterYear","EasterDate"