SQL Server如何查询实现多行值转单行 展示员工近3年数据
SQL Server 动态实现近3年IssueDate按年列转行方案
实现逻辑
- 采用动态SQL自动生成近3年的年份列,无需硬编码年份,每次执行自动适配时间范围
- 用PIVOT算子完成行转列,按
EmpID、Dept、ItemCode三个维度聚合,无数据的年份列默认返回空值 - 提前过滤近3年数据减少计算量,支持自定义同一年多条记录的聚合规则
通用查询代码
-- 定义变量存储动态列名、待执行SQL DECLARE @YearCols NVARCHAR(MAX), @ExecSQL NVARCHAR(MAX); -- 生成最近3个自然年的列名(以当前系统年份为基准,倒序排列) SELECT @YearCols = STRING_AGG(QUOTENAME(Yr), ',') WITHIN GROUP (ORDER BY Yr DESC) FROM ( SELECT YEAR(GETDATE()) AS Yr UNION ALL SELECT YEAR(GETDATE()) - 1 UNION ALL SELECT YEAR(GETDATE()) - 2 ) YearRange; -- 拼接最终查询语句 SET @ExecSQL = N' SELECT EmpID, Dept, ItemCode, ' + @YearCols + ' FROM ( SELECT EmpID, Dept, ItemCode, YEAR(IssueDate) AS DataYear, -- 同维度同一年有多条记录时默认用逗号拼接所有日期,可按需替换为MIN/MAX取单值 STRING_AGG(CONVERT(VARCHAR(10), IssueDate, 120), '','') AS DateValue FROM 替换为你的实际源表名 -- 过滤近3年数据,减少无效计算 WHERE IssueDate >= DATEADD(YEAR, -3, DATEFROMPARTS(YEAR(GETDATE()), 1, 1)) GROUP BY EmpID, Dept, ItemCode, YEAR(IssueDate) ) SourceData PIVOT ( MAX(DateValue) FOR DataYear IN (' + @YearCols + ') ) PivotResult ORDER BY EmpID, Dept, ItemCode;'; -- 执行动态语句 EXEC sp_executesql @ExecSQL;
适配说明
- 使用前将代码中
替换为你的实际源表名改为业务中对应的表名即可直接运行 - 若同维度+同一年份仅需展示最早/最晚的IssueDate,将子查询中的
STRING_AGG(CONVERT(VARCHAR(10), IssueDate, 120), ',')替换为MIN(CONVERT(VARCHAR(10), IssueDate, 120))或MAX(CONVERT(VARCHAR(10), IssueDate, 120))即可 - 若需要以源表内最新IssueDate所在年份为基准计算近3年(而非当前系统时间),替换年份列生成逻辑为以下代码即可:
SELECT @YearCols = STRING_AGG(QUOTENAME(Yr), ',') WITHIN GROUP (ORDER BY Yr DESC) FROM ( SELECT YEAR(MAX(IssueDate)) AS Yr FROM 替换为你的实际源表名 UNION ALL SELECT YEAR(MAX(IssueDate))-1 FROM 替换为你的实际源表名 UNION ALL SELECT YEAR(MAX(IssueDate))-2 FROM 替换为你的实际源表名 ) YearRange;
- 若使用SQL Server 2016及以下版本(不支持
STRING_AGG函数),将字符串聚合逻辑替换为FOR XML PATH写法即可兼容。
内容的提问来源于stack exchange,提问作者sk1007
相关产品推荐
相关产品推荐

