使用PIVOT / UNPIVOT将行转换为列

时间:2010-09-10 15:36:06

标签: sql pivot unpivot

我一直在阅读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

感谢您的帮助!

2 个答案:

答案 0 :(得分:0)

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

答案 1 :(得分:0)

根据您的评论,您希望通过动态版本执行此操作。您可以将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