如何在T-SQL中实现计算月份内ISO周数的函数
T-SQL 计算指定月份包含的ISO周数(按周日归属月份规则)
根据你的需求,一周归属的月份以该周星期日所在月份为准,以下是实现自定义函数GetNumberOfIsoWeeksInMonth的具体方案,可直接用于计算指定年、月对应的ISO周数量,进而完成月度平均人员配置需求的计算。
函数实现代码
CREATE FUNCTION dbo.GetNumberOfIsoWeeksInMonth( @Year INT, @Month INT ) RETURNS INT AS BEGIN -- 获取指定月份的首尾日期 DECLARE @FirstDayOfMonth DATE = DATEFROMPARTS(@Year, @Month, 1); DECLARE @LastDayOfMonth DATE = EOMONTH(@FirstDayOfMonth); -- 扩展日期范围:覆盖可能归属当前月的前后周日 DECLARE @StartDate DATE = DATEADD(DAY, -(DATEPART(WEEKDAY, @FirstDayOfMonth) - 1), @FirstDayOfMonth); DECLARE @EndDate DATE = DATEADD(DAY, 7 - DATEPART(WEEKDAY, @LastDayOfMonth), @LastDayOfMonth); DECLARE @WeeksCount INT; -- 生成所有周日序列,筛选归属当前月的周日,统计对应的ISO周数(去重) WITH DateRange AS ( SELECT @StartDate AS DateVal UNION ALL SELECT DATEADD(DAY, 7, DateVal) FROM DateRange WHERE DateVal <= @EndDate ) SELECT @WeeksCount = COUNT(DISTINCT DATEPART(ISO_WEEK, DateVal)) FROM DateRange WHERE MONTH(DateVal) = @Month AND YEAR(DateVal) = @Year; RETURN @WeeksCount; END;
代码逻辑说明
- 确定日期范围:先获取指定月份的首尾日期,再扩展到前后最近的周日,确保不会遗漏归属当前月的边缘周。
- 生成周日序列:用递归CTE生成范围内所有间隔7天的周日日期。
- 筛选统计:只保留所在月份为目标月的周日,提取对应的ISO周编号,去重后计数即为结果。
测试示例
- 计算2024年2月的ISO周数(应返回5,包含第5-9周):
SELECT dbo.GetNumberOfIsoWeeksInMonth(2024, 2); - 计算2024年1月的ISO周数(应返回4,仅包含第1-4周):
SELECT dbo.GetNumberOfIsoWeeksInMonth(2024, 1);
用于人员配置计算
直接调用函数即可完成月度平均需求计算,注意整数除法需转浮点避免精度丢失:
SELECT CAST(WeeklyStaffingNeedsTotal AS FLOAT) / dbo.GetNumberOfIsoWeeksInMonth(Year, Month) AS MonthlyStaffingNeed FROM YourStaffingTable;
内容的提问来源于stack exchange,提问作者comichael
相关产品推荐
相关产品推荐

