You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Snowflake SQL计算澳大利亚各州下一个工作日问题排查

排查Snowflake SQL中澳大利亚ACT州下一个工作日计算错误的思路

核心问题定位

你的代码中下一个工作日计算逻辑存在根本性错误,以下是具体排查方向和修正建议:


1. PARTITION BY的逻辑完全错误

你当前使用PARTITION BY "ACT Work Day" ='Work Day'来分组,这会把数据拆成两个独立分组:

  • 一组是"ACT Work Day"='Work Day'的所有工作日
  • 另一组是"ACT Work Day" IS NULL的所有非工作日

在非工作日的分组里调用LEAD("Report Date"),只会返回该分组内的下一个非工作日日期,完全达不到"找下一个工作日"的目的。

2. "ACT Work Day"字段定义不完整

当前CASE语句仅在非假期且非周末时标记为'Work Day',其余情况该字段为NULL。这会导致后续窗口函数和判断逻辑出现空值异常,应该明确区分工作日和非工作日:

CASE 
    WHEN "ACT Public Holiday" IS NULL THEN 'Work Day'
    ELSE 'Non-Work Day'
END AS "ACT Work Day"

3. DISTINCT可能干扰窗口函数结果

如果V_D_CALENDAR表是每日一条数据,DISTINCT是多余的;如果假期表存在重复匹配(比如同一天有多个假期记录),DISTINCT会导致日期行被去重,打乱LEAD函数的连续日期序列,进而计算错误。

4. 假期匹配的验证

需要确认ACT州的假期关联是否正确:

  • 检查IS_ALL_NODES='Y'的全国假期是否正确关联到ACT州
  • 验证NODE_ID='ACT'的专属假期是否和日历日期正确匹配
  • 可以单独执行以下语句排查假期匹配结果:
SELECT C."Report Date", ACT.holiday_name
FROM "ODS"."DWBI_DATAHUB"."V_D_CALENDAR" C
LEFT JOIN "ODS"."ODS"."DS_ALLIANCE_HOLIDAY" ACT 
  ON C."Report Date" = ACT.HOLIDAY_DATE 
  AND (ACT.IS_ALL_NODES = 'Y' OR ACT.NODE_ID = 'ACT')
WHERE C."Report Date" BETWEEN '2024-01-01' AND '2024-01-10'
ORDER BY C."Report Date";

正确的下一个工作日计算思路

方法1:使用窗口函数标记并取后续第一个工作日

先标记所有工作日,再用LEAD结合条件判断找到下一个工作日:

WITH calendar_with_workday AS (
    SELECT 
        "Report Date",
        "Calendar Day in Week",
        -- 标记ACT州的非工作日:周末+公共假期
        CASE 
            WHEN ACT.holiday_name IS NOT NULL OR "Calendar Day in Week" IN ('Sat','Sun') 
            THEN 'Non-Work Day'
            ELSE 'Work Day'
        END AS "ACT Work Day"
    FROM "ODS"."DWBI_DATAHUB"."V_D_CALENDAR" C
    LEFT JOIN "ODS"."ODS"."DS_ALLIANCE_HOLIDAY" ACT 
        ON C."Report Date" = ACT.HOLIDAY_DATE 
        AND (ACT.IS_ALL_NODES = 'Y' OR ACT.NODE_ID = 'ACT')
    WHERE "Report Date" IS NOT NULL
),
workday_next AS (
    SELECT 
        *,
        -- 取当前日期之后第一个工作日
        LEAD(CASE WHEN "ACT Work Day" = 'Work Day' THEN "Report Date" END) 
            OVER (ORDER BY "Report Date") AS "ACT Next Work Day"
    FROM calendar_with_workday
)
-- 填充连续非工作日的下一个工作日
SELECT 
    "Report Date",
    "Calendar Day in Week",
    "ACT Work Day",
    LAST_VALUE("ACT Next Work Day") IGNORE NULLS 
        OVER (ORDER BY "Report Date" ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING) AS "ACT Next Work Day"
FROM workday_next
ORDER BY "Report Date";

方法2:使用Snowflake的递归CTE(适合批量计算)

如果需要处理大量日期,递归CTE可以逐个日期查找下一个工作日:

WITH RECURSIVE calendar_base AS (
    SELECT 
        "Report Date",
        CASE 
            WHEN ACT.holiday_name IS NOT NULL OR "Calendar Day in Week" IN ('Sat','Sun') 
            THEN FALSE
            ELSE TRUE
        END IS_WORKDAY
    FROM "ODS"."DWBI_DATAHUB"."V_D_CALENDAR" C
    LEFT JOIN "ODS"."ODS"."DS_ALLIANCE_HOLIDAY" ACT 
        ON C."Report Date" = ACT.HOLIDAY_DATE 
        AND (ACT.IS_ALL_NODES = 'Y' OR ACT.NODE_ID = 'ACT')
    WHERE "Report Date" IS NOT NULL
),
next_workday AS (
    SELECT 
        "Report Date",
        IS_WORKDAY,
        CASE WHEN IS_WORKDAY THEN "Report Date" ELSE NULL END AS NEXT_WORKDAY
    FROM calendar_base
    UNION ALL
    SELECT 
        cb."Report Date",
        cb.IS_WORKDAY,
        nw.NEXT_WORKDAY
    FROM calendar_base cb
    JOIN next_workday nw 
        ON cb."Report Date" = DATEADD(DAY, -1, nw."Report Date")
    WHERE cb.IS_WORKDAY = FALSE AND nw.NEXT_WORKDAY IS NOT NULL
)
SELECT DISTINCT "Report Date", IS_WORKDAY, NEXT_WORKDAY AS "ACT Next Work Day"
FROM next_workday
ORDER BY "Report Date";

内容的提问来源于stack exchange,提问作者Appocalypse

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 21:35:22