如何修正SQL函数以计算月中/月末入职员工的月度每周休息日
修复SQL自定义函数GetTotalWeekHoliday,统计入职后的有效周休息日
原函数存在的问题:会忽略员工入职日期,始终返回整月的指定周休息日数量,无法区分入职前后的有效休息日。比如1月有5个周二,员工1月20日入职时,预期返回2,但原函数返回5。
修改后的函数代码
GO /****** Object: UserDefinedFunction [dbo].[GetTotalWeekHoliday] Script Date: 1/23/2024 12:12:04 PM ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO ALTER FUNCTION [dbo].[GetTotalWeekHoliday] ( @HireDate AS DATE, -- 员工入职日期 @HolidayName AS NVARCHAR(50) -- 指定的周休息日名称(如'Tuesday') ) RETURNS INT AS BEGIN DECLARE @Count INT = 0; -- 获取当月第一天 DECLARE @MonthStart DATE = DATEFROMPARTS(YEAR(@HireDate), MONTH(@HireDate), 1); -- 获取当月最后一天 DECLARE @MonthEnd DATE = EOMONTH(@HireDate); -- 遍历起始日期:取入职日期与当月第一天的较大值,确保只统计入职后日期 DECLARE @CurrentDate DATE = CASE WHEN @HireDate > @MonthStart THEN @HireDate ELSE @MonthStart END; WHILE @CurrentDate <= @MonthEnd BEGIN DECLARE @DayName VARCHAR(20); SELECT @DayName = CASE (DATEPART(dw, @CurrentDate) + @@DATEFIRST) % 7 WHEN 1 THEN 'Sunday' WHEN 2 THEN 'Monday' WHEN 3 THEN 'Tuesday' WHEN 4 THEN 'Wednesday' WHEN 5 THEN 'Thursday' WHEN 6 THEN 'Friday' WHEN 0 THEN 'Saturday' END; IF @DayName = @HolidayName BEGIN SET @Count += 1; END SET @CurrentDate = DATEADD(DAY, 1, @CurrentDate); END RETURN @Count; END;
关键修改说明
- 精简参数:移除原函数中冗余的
@Month、@year和@count1参数,直接从入职日期@HireDate提取年月信息,计数变量内部初始化,避免外部传入的无效值干扰。 - 修正遍历起点:不再强制从当月第一天开始遍历,而是取入职日期和当月第一天的较大值,确保只统计员工入职后的休息日。
- 优化日期边界计算:使用
EOMONTH函数直接获取当月最后一天,替代原逻辑中依赖循环判断月份的低效方式。 - 边界场景处理:若员工入职日期晚于目标月份,函数会返回0,符合业务逻辑。
测试验证
以问题中的例子测试:员工1月20日入职,指定休息日为'Tuesday',1月的周二为2日、9日、16日、23日、30日,入职后有效休息日为23日、30日,函数返回结果为2,符合预期。
内容的提问来源于stack exchange,提问作者naeemshah1
相关产品推荐
相关产品推荐

