无聚合SQL数据转置求助:PIVOT等方法尝试失败
SQL 无聚合转置解决方案
你的需求本质是先逆透视(UNPIVOT)将列转为行,再透视(PIVOT)将行转为列的组合操作,之前失败大概率是逆透视时没做好指标名称的映射,或者透视时未正确关联维度。以下是针对你数据集的具体实现:
假设你的源表名为BudgetData,结构与你给出的一致,执行以下SQL语句即可得到目标结果:
-- 第一步:逆透视,将原表的数值列转为行,并映射为中文指标名 WITH Unpivoted AS ( SELECT Header, CASE WHEN Metric = 'Contract Value' THEN '合同金额' WHEN Metric = 'Total Cost' THEN '总成本' WHEN Metric = 'Profit' THEN '利润' END AS MetricName, MetricValue FROM BudgetData UNPIVOT ( MetricValue FOR Metric IN ([Contract Value], [Total Cost], [Profit]) ) AS Up ), -- 第二步:透视,将Header转为列,指标名作为行 Pivoted AS ( SELECT MetricName AS Header, [初始预算], [变更订单] FROM Unpivoted PIVOT ( MAX(MetricValue) FOR Header IN ([初始预算], [变更订单]) ) AS Pv ) SELECT * FROM Pivoted;
关键说明:
- 逆透视阶段:通过
UNPIVOT把原表的Contract Value/Total Cost/Profit三列拆成Metric(原列名)和MetricValue(对应数值),同时用CASE把英文列名替换成你需要的中文指标名(合同金额/总成本/利润)。 - 透视阶段:用
PIVOT把Header列的两个值(初始预算/变更订单)转为新的列,这里用MAX聚合是因为每个指标-Header组合只有一个值,聚合函数不会改变结果,完全符合你“无聚合直接转置”的需求。
如果你的数据库不支持UNPIVOT/PIVOT(比如某些轻量数据库),也可以用兼容性更强的写法:
SELECT MetricName AS Header, MAX(CASE WHEN Header = '初始预算' THEN MetricValue END) AS [初始预算], MAX(CASE WHEN Header = '变更订单' THEN MetricValue END) AS [变更订单] FROM BudgetData CROSS APPLY ( VALUES ('合同金额', [Contract Value]), ('总成本', [Total Cost]), ('利润', [Profit]) ) AS CA(MetricName, MetricValue) GROUP BY MetricName;
这个写法通过CROSS APPLY生成指标名-数值的行,再用CASE+MAX把不同Header的值转为列,逻辑和前一种方案完全一致,适配更多数据库环境。
内容的提问来源于stack exchange,提问作者jeff
相关产品推荐
相关产品推荐

