使用 PIVOT/UNPIVOT 将行转换为列
Posted
技术标签:
【中文标题】使用 PIVOT/UNPIVOT 将行转换为列【英文标题】:Using PIVOT/UNPIVOT to convert rows to columns 【发布时间】:2010-09-10 15:36:05 【问题描述】:我一直在阅读关于 PIVOT 和 UNPIVOT 的内容,但未能正确格式化结果以呈现数据。这是我的源表:
StepID | ShortDesc | Type_1 | ar1 | ar2
1 ShortDesc1 10 11.11 11.01
2 ShortDesc2 20 22.22 22.02
3 ShortDesc3 30 33.33 33.03
4 ShortDesc4 40 44.44 44.04
5 ShortDesc5 50 55.55 55.05
这是我想要达到的结果:
| Step1 | Step2 | Step3 | Step4 | Step5
ShortDesc1 ShortDesc2 ShortDesc3 ShortDesc4 ShortDesc5
10 20 30 40 50
11.11 22.22 33.33 44.44 55.55
11.01 22.02 33.03 44.04 55.05
这是我尝试过的最新方法,当然没用:
DROP TABLE ProductionTest
CREATE TABLE ProductionTest (StepID int, ShortDesc nvarchar(25), Type_1 int, ar1 real, ar2 real)
INSERT INTO ProductionTest VALUES (1, 'Short Desc 1', 10, 11.11, 11.01)
INSERT INTO ProductionTest VALUES (2, 'Short Desc 2', 20, 22.22, 22.02)
INSERT INTO ProductionTest VALUES (3, 'Short Desc 3', 30, 33.33, 33.03)
INSERT INTO ProductionTest VALUES (4, 'Short Desc 4', 40, 44.44, 44.04)
INSERT INTO ProductionTest VALUES (5, 'Short Desc 5', 50, 55.55, 55.05)
SELECT * FROM ProductionTest
SELECT [1]as Step1, [2] as Step2, [3]as Step3, [4]as Step4, [5]as Step5
FROM ( SELECT [StepID], ShortDesc, Type_1, ar1, ar2
FROM ProductionTest) p
PIVOT (MAX(ShortDesc)
FOR StepID IN ([1], [2], [3], [4], [5])
) AS pvt
感谢您的帮助!
【问题讨论】:
【参考方案1】:Pivot 不会旋转整个表格。我认为您需要类似的东西
SELECT [1]as Step1, [2] as Step2, [3]as Step3, [4]as Step4, [5]as Step5
FROM ( SELECT [StepID], ShortDesc
FROM ProductionTest) p
PIVOT (MAX(ShortDesc)
FOR StepID IN ([1], [2], [3], [4], [5])
) AS pvt
UNION ALL
SELECT [1]as Step1, [2] as Step2, [3]as Step3, [4]as Step4, [5]as Step5
FROM ( SELECT [StepID], CAST(Type_1 AS nvarchar(25)) AS Type_1
FROM ProductionTest) p
PIVOT (MAX(Type_1)
FOR StepID IN ([1], [2], [3], [4], [5])
) AS pvt
UNION ALL
SELECT [1]as Step1, [2] as Step2, [3]as Step3, [4]as Step4, [5]as Step5
FROM ( SELECT [StepID], CAST(ar1 AS nvarchar(25)) AS ar1
FROM ProductionTest) p
PIVOT (MAX(ar1)
FOR StepID IN ([1], [2], [3], [4], [5])
) AS pvt
UNION ALL
SELECT [1]as Step1, [2] as Step2, [3]as Step3, [4]as Step4, [5]as Step5
FROM ( SELECT [StepID], CAST(ar2 AS nvarchar(25)) AS ar2
FROM ProductionTest) p
PIVOT (MAX(ar2)
FOR StepID IN ([1], [2], [3], [4], [5])
) AS pvt
【讨论】:
谢谢,这行得通,虽然确实比我最初认为的要复杂得多。你的权利,我真正需要做的是“翻转”桌子。这给了我一个很好的起点。再次感谢!! 实际上,如果可以的话,还有一个后续问题。使这种动态与静态变得多么困难。我最初的想法是创建一个数据库视图和/或存储过程。你怎么看?【参考方案2】:根据您希望通过动态版本执行此操作的评论。您可以将 Martin 的版本用于静态版本,但如果您想要动态版本,这意味着 StepID's
的数量会发生变化,那么您可以执行以下操作:
DECLARE @cols AS NVARCHAR(MAX),
@colsAlias AS NVARCHAR(MAX),
@query AS NVARCHAR(MAX);
select @cols = STUFF((SELECT distinct ',' + QUOTENAME(StepID)
from ProductionTest
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
SELECT @colsAlias = STUFF((SELECT DISTINCT ',' + QUOTENAME(p.StepID) + ' AS ' + QUOTENAME('Step' + Cast(p1.StepID as varchar(10)))
FROM ProductionTest p INNER JOIN ProductionTest p1 ON p.StepID = p1.StepID
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'),1,1,'')
set @query = 'SELECT ' + @colsAlias + ' from
(
select [StepID], ShortDesc
FROM ProductionTest
) x
pivot
(
MAX(ShortDesc)
for stepId in (' + @cols + ')
) p
UNION ALL
SELECT ' + @colsAlias + ' from
(
select [StepID], CAST(Type_1 AS nvarchar(25)) AS Type_1
FROM ProductionTest
) x
pivot
(
MAX(Type_1)
for stepId in (' + @cols + ')
) p
UNION ALL
SELECT ' + @colsAlias + ' from
(
select [StepID], CAST(ar1 AS nvarchar(25)) AS ar1
FROM ProductionTest
) x
pivot
(
MAX(ar1)
for stepId in (' + @cols + ')
) p
UNION ALL
SELECT ' + @colsAlias + ' from
(
select [StepID], CAST(ar2 AS nvarchar(25)) AS ar2
FROM ProductionTest
) x
pivot
(
MAX(ar2)
for stepId in (' + @cols + ')
) p '
execute (@query)
查询仍然很复杂,但会在查询运行时创建列。
这是SQL Fiddle with a Demo
【讨论】:
以上是关于使用 PIVOT/UNPIVOT 将行转换为列的主要内容,如果未能解决你的问题,请参考以下文章
在 Sql Server 中使用 Pivot/unpivot 将单行转换为单列
将矩阵转换为 3 列表('reverse pivot'、'unpivot'、'flatten'、'normalize')