求助编写SQL脚本:获取过去3年每月最后一个工作日(排除周末及法定假日)
可行SQL脚本方案
核心思路
先锁定过去3年的日期范围,标记每个日期是否为工作日(排除周末)、是否属于法定假日;再提取每个月的月末日期,从月末往前排查,找到第一个既非周末也非法定假日的日期,即为当月最后一个工作日。
完整SQL脚本(以SQL Server为例)
WITH DateRange AS ( -- 筛选过去3年的日期,同时标记工作日/法定假日属性 SELECT a.FullDate, DATEFROMPARTS(YEAR(a.FullDate), MONTH(a.FullDate), 1) AS MonthStart, -- 标记是否为工作日:排除周六(7)、周日(1),需根据数据库规则调整 CASE WHEN DATEPART(WEEKDAY, a.FullDate) IN (1, 7) THEN 0 ELSE 1 END AS IsWorkDay, -- 标记是否为法定假日:关联Table2判断 CASE WHEN b.DateId IS NOT NULL THEN 1 ELSE 0 END AS IsHoliday FROM Table1 a LEFT JOIN Table2 b ON a.DateId = b.DateId WHERE a.FullDate BETWEEN DATEADD(YEAR, -3, GETDATE()) AND GETDATE() ), MonthEnds AS ( -- 提取每个月的最后一天 SELECT MonthStart, MAX(FullDate) AS MonthEndDate FROM DateRange GROUP BY MonthStart ), CandidateDates AS ( -- 从月末往前生成最多3天的候选日期(覆盖周末+可能的1天假日) SELECT me.MonthStart, DATEADD(DAY, -n.Number, me.MonthEndDate) AS CandidateDate FROM MonthEnds me CROSS JOIN (VALUES (0), (1), (2), (3)) n(Number) ), ValidWorkDays AS ( -- 筛选有效工作日,并按月份排序候选日期 SELECT cd.CandidateDate, cd.MonthStart, ROW_NUMBER() OVER (PARTITION BY cd.MonthStart ORDER BY cd.CandidateDate DESC) AS rn FROM CandidateDates cd JOIN DateRange dr ON cd.CandidateDate = dr.FullDate WHERE dr.IsWorkDay = 1 AND dr.IsHoliday = 0 ) -- 取每个月的第一个有效日期(即当月最后一个工作日) SELECT CandidateDate AS WeekDay_FullDate_Past3yrs FROM ValidWorkDays WHERE rn = 1 ORDER BY CandidateDate;
关键说明
- 工作日判断:
DATEPART(WEEKDAY, FullDate)的返回值随数据库不同有差异,比如MySQL中周日是0、周六是6,需根据实际环境调整排除的数值。 - 法定假日关联:若Table2的
Statutory_Holidays是状态字段(如'Y'表示假日),需将CASE WHEN b.DateId IS NOT NULL改为CASE WHEN b.Statutory_Holidays = 'Y'。 - 候选日期范围:往前推3天足以覆盖绝大多数情况,若存在连续3天以上假日(如春节长假),可适当扩大
CROSS JOIN的数字范围(比如加到5)。
内容的提问来源于stack exchange,提问作者David Jones
相关产品推荐
相关产品推荐

