求可排除节假日的SQL函数:获取当前日期前第5个工作日
实现排除周末与公共假日的“前第5个工作日”SQL函数
嘿,你的现有思路已经很靠谱了!要解决公共假日的问题,核心是得有一个专门存储公共假日的表——毕竟假日是动态变化的,没法直接硬编码在逻辑里。下面给你一步步实现完整的方案:
第一步:创建公共假日表
首先建一张表来存储所有公共假日,结构简单直接,方便后续维护:
CREATE TABLE Holidays ( HolidayDate DATE NOT NULL PRIMARY KEY, -- 假日日期(唯一主键) HolidayName NVARCHAR(100) NOT NULL -- 假日名称(可选,用于标识) ); -- 示例插入假日数据(根据你的实际需求补充/更新) INSERT INTO Holidays (HolidayDate, HolidayName) VALUES ('2018-01-01', '元旦'), ('2018-02-16', '春节'), ('2018-04-05', '清明节');
第二步:编写SQL函数
这里用CTE生成日期范围,再筛选出符合条件的工作日,最后取第5个。这个方案还兼容SQL Server的@@DATEFIRST设置(避免不同服务器星期起始日不同导致的判断错误):
CREATE FUNCTION dbo.GetPrevious5thWorkday() RETURNS DATE AS BEGIN DECLARE @TargetDate DATE; -- CTE生成当前日期往前推14天的所有日期(足够覆盖周末+连续假日的极端情况) WITH DateRange AS ( SELECT DATEADD(DAY, -n, CAST(GETDATE() AS DATE)) AS WorkDate FROM ( VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11),(12),(13),(14) ) AS Numbers(n) ) -- 筛选工作日、排除假日,排序后取第5个 SELECT @TargetDate = WorkDate FROM ( SELECT WorkDate, ROW_NUMBER() OVER (ORDER BY WorkDate DESC) AS RowNum FROM DateRange WHERE -- 排除周末:兼容不同的DATEFIRST设置 DATEPART(WEEKDAY, WorkDate) NOT IN ( CASE WHEN @@DATEFIRST = 7 THEN 1 ELSE 7 END, -- 周日 CASE WHEN @@DATEFIRST = 7 THEN 7 ELSE 1 END -- 周六 ) -- 排除公共假日 AND WorkDate NOT IN (SELECT HolidayDate FROM Holidays) ) AS FilteredDates WHERE RowNum = 5; RETURN @TargetDate; END;
第三步:调用函数
直接执行下面的语句就能得到目标日期:
SELECT dbo.GetPrevious5thWorkday();
关键注意事项
- 假日表维护:记得定期更新
Holidays表,添加新的公共假日,不然函数会漏掉新的假日哦 - 性能优化:如果是高并发场景,标量函数可能有性能瓶颈,可以改成表值函数或者直接用CTE查询代替函数
- 多地区支持:如果需要处理不同地区的假日,可以给
Holidays表加Region字段,函数里新增@Region参数来筛选对应地区的假日
内容的提问来源于stack exchange,提问作者Vicky S
相关产品推荐
相关产品推荐

