SQL Server 2012中Pivot/Unpivot数据转置需求实现咨询
SQL Server 2012 行列转换优化方案
你的思路完全正确:先将PAC_Contract、PAC_Projected_Cost、JTD_Actual_Cost列列转行,再对Month_End列行转列,是匹配你需求的标准方案。但当前用三次UNION的写法确实繁琐,且多次扫描表影响效率,推荐用更简洁高效的CROSS APPLY VALUES语法替代。
原始表结构说明
表_rec_spectrum_CTC_Master包含字段:Job_Number(工单编号)、Month_End(月末日期)、PAC_Contract(合同金额)、PAC_Projected_Cost(预计成本)、JTD_Actual_Cost(累计实际成本),每个工单对应多条不同月末日期的记录。
期望结果说明
输出以Job_Number为分组,将三个成本指标转为行,同时将最近3个月末日期转为列,每个指标行对应显示对应月份的数值。
优化后的动态SQL代码
DECLARE @columns NVARCHAR(MAX) = '', @sql NVARCHAR(MAX) = ''; -- 获取最近3个月末日期,拼接为Pivot所需的列名 SELECT TOP 3 @columns += QUOTENAME(Month_End) + ',' FROM _rec_spectrum_CTC_Master GROUP BY Month_End ORDER BY Month_End DESC; -- 移除最后一个逗号 SET @columns = LEFT(@columns, LEN(@columns) - 1); -- 构建列转行+行转列的SQL语句 SET @sql = N' SELECT Job_Number, Column_Name, ' + @columns + N' FROM ( -- 使用CROSS APPLY VALUES一次性完成列转行,同时指定友好列名 SELECT Job_Number, Month_End, Column_Name, Value FROM _rec_spectrum_CTC_Master WHERE Job_Number = ''A1327'' CROSS APPLY ( VALUES (''PAC Contract'', PAC_Contract), (''PAC Projected Cost'', PAC_Projected_Cost), (''JTD Actual Cost'', JTD_Actual_Cost) ) AS ca (Column_Name, Value) ) AS d -- 对月末日期执行行转列 PIVOT ( SUM(Value) FOR Month_End IN (' + @columns + N') ) AS ppc;'; EXECUTE sp_executesql @sql;
优化点说明
- 替换三次UNION为CROSS APPLY VALUES:仅扫描一次原始表,避免重复查询,效率更高;代码行数更少,逻辑更直观。
- 直接生成友好列名:在列转行的同时就指定了“PAC Contract”这类易读的列名,无需后续替换操作,维护更方便。
- 保留动态Pivot逻辑:依然自动获取最近3个月末日期,适配数据的动态变化。
内容的提问来源于stack exchange,提问作者jeff
相关产品推荐
相关产品推荐

