SQL Server存储过程开发:指定月份起24个月员工月度统计
员工入职月度统计存储过程解决方案
原查询问题分析
原查询语句的核心问题是仅按月份数字分组,会将不同年份的同一个月数据合并(比如2022年12月和2023年12月的入职数会被统计到一起),同时时间范围限定为当年年初至今,不符合“从指定月份起过去24个月”的需求。
原查询中文翻译:
SELECT MAX(DATENAME(MM,[join_date])) AS 月份, COUNT(1) AS "入职总人数" FROM [EMP_TABLE] WHERE [join_date] BETWEEN DATEADD(yy, DATEDIFF(yy,0,GETDATE()), 0) AND GETDATE() GROUP BY MONTH([join_date]);
解决方案:创建指定存储过程
以下是符合需求的SQL Server存储过程,支持传入年份和月份参数,统计该月份起过去24个月的每月入职人数,月份格式为「Dec 22」,且不会合并跨年份的同月数据:
CREATE PROCEDURE GetEmployeeHireStats @InputYear INT, @InputMonth INT AS BEGIN SET NOCOUNT ON; -- 计算统计时间范围:从指定月份往前推23个月的第一天,到指定月份的最后一天(共24个月) DECLARE @StartDate DATE = DATEADD(MONTH, -23, DATEFROMPARTS(@InputYear, @InputMonth, 1)); DECLARE @EndDate DATE = EOMONTH(DATEFROMPARTS(@InputYear, @InputMonth, 1)); -- 生成需要统计的所有月份序列 WITH MonthRange AS ( SELECT @StartDate AS MonthStart UNION ALL SELECT DATEADD(MONTH, 1, MonthStart) FROM MonthRange WHERE DATEADD(MONTH, 1, MonthStart) <= @EndDate ) -- 关联员工表统计每月入职人数 SELECT FORMAT(m.MonthStart, 'MMM yy') AS 月份, COUNT(e.emp_id) AS 入职总人数 FROM MonthRange m LEFT JOIN employee e ON e.join_date >= m.MonthStart AND e.join_date <= EOMONTH(m.MonthStart) GROUP BY m.MonthStart ORDER BY m.MonthStart; END
关键说明
- 时间范围计算:通过
DATEFROMPARTS将传入的年月参数转为指定月份的第一天,再往前推23个月得到起始日期,确保覆盖整整24个月; - 月份序列生成:用递归CTE生成所有需要统计的月份,即使某月份没有员工入职,也会在结果中显示0,避免遗漏;
- 分组逻辑:按每个月的起始日期(
MonthStart)分组,而非仅按月份数字,彻底解决跨年份同月数据合并的问题; - 格式输出:使用
FORMAT函数直接生成「MMM yy」格式的月份名称(如「Dec 22」); - 左关联保证完整性:通过
LEFT JOIN确保所有生成的月份都出现在结果中,不会因为无入职数据而消失。
存储过程调用示例
若要查询2023年10月起过去24个月的入职统计,执行以下语句:
EXEC GetEmployeeHireStats @InputYear = 2023, @InputMonth = 10;
内容的提问来源于stack exchange,提问作者Kalai Selvi
相关产品推荐
相关产品推荐

