列到行SQL语法

时间:2015-03-26 07:04:42

标签: sql sql-server sql-server-2008

我有下表:

--------------------------------------------
Group   Date         Value1   Value2   Value3
--------------------------------------------
A       2014-01-01   10       10       5
B       2014-01-01   12       20       25
C       2014-01-01   20       40       50

我希望得到以下结果:

-------------------------------------------
NewCol     A      B      C
-------------------------------------------
Value1     10     12     20
Value2     10     20     40
Value3     5      25     50

如何在sql server 2008中执行此操作?谢谢。

4 个答案:

答案 0 :(得分:1)

您可以使用PIVOT运算符。请参阅以下详细信息:

select 'Value1' NewCol, A, B, C
from (select [Group], Value1 Value from YourTable) g
pivot (
  max(g.Value)
  for g.[Group] in (A, B, C)) p
union all
select 'Value2', A, B, C
from (select [Group], Value2 Value from YourTable) g
pivot (
  max(g.Value)
  for g.[Group] in (A, B, C)) p
union all  
select 'Value3', A, B, C
from (select [Group], Value3 Value from YourTable) g
pivot (
  max(g.Value)
  for g.[Group] in (A, B, C)) p

或者您可以组合PIVOT和UNPIVOT运算符:

select NewCol, A, B, C
from (
  select *
  from YourTable
  unpivot (
    Value
    for NewCol in (Value1, Value2, Value3)
  ) up
) up
pivot (
  max(Value)
  for [Group] in (A, B, C)
) p

答案 1 :(得分:1)

要交换行和列,您需要先UNPIVOT(将列转换为行值),然后根据PIVOT结果UNPIVOT(行到列)。

-- Here is the result 
SELECT * FROM 
(
    -- Unpivot here using CROSS APPLY
    SELECT [Group],
    [Values],COLNAMES 
    FROM YOURTABLE
    CROSS APPLY(VALUES (Value1,'Value1'),(Value2,'Value2'),(Value3,'Value3'))
    AS COLUMNNAMES([Values],COLNAMES)
)TAB
PIVOT
(
     -- Specify the values to hold in pivoted column
     MIN([Values])
     -- Specify the name of columns
     FOR [Group] IN([A],[B],[C])
)P
ORDER BY COLNAMES

查询的工作

您可以CROSS APPLY使用UNPIVOTValue1将保留列中的值 - Value1'Value1'(在单引号中)将是硬编码列名称值(显示在COLNAMES变量中。CROSS APPLY的使用将生成以下结果。

enter image description here

现在使用CROSS APPLY生成的数据,您将转到PIVOT,形成以下结果。

enter image description here

有时您无法事先知道列Group中的值。在这种情况下,您需要使用Dynamic Sql。第一步是将行Group中的值变为变量。

DECLARE @cols NVARCHAR (MAX)

SELECT @cols = STUFF((SELECT ',' + QUOTENAME([Group]) 
            FROM 
            (
                SELECT distinct [Group] from YOURTABLE
            ) c
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

现在使用PIVOT查询Dynamic Sql。我们使用Dynamic Sql的原因是因为Sql Server无法从变量中获取列名,除非使用Dynamic Sql

DECLARE @query NVARCHAR(MAX)
SET @query = '
            SELECT * FROM 
             (
                -- Unpivot here using CROSS APPLY
                SELECT [Group],
                [Values],COLNAMES 
                FROM YOURTABLE
                CROSS APPLY(VALUES (Value1,''Value1''),(Value2,''Value2''),(Value3,''Value3''))
                AS COLUMNNAMES([Values],COLNAMES)
             ) x
             PIVOT 
             (
                 -- Specify the values to hold in pivoted column
                 MIN([Values])
                 -- Get the column names from variable
                 FOR [Group] IN('+@cols+')
            ) p            
            ORDER BY COLNAMES;'     

EXEC SP_EXECUTESQL @query

希望您了解概念并获得结果 任何澄清,随时可以询问。

答案 2 :(得分:0)

使用PIVOT功能。那会给你答案。

PIVOT功能

的示例
  SELECT <non-pivoted column>,
        [first pivoted column] AS <column name>,
        [second pivoted column] AS <column name>,
        ...
        [last pivoted column] AS <column name>
    FROM
        (<SELECT query that produces the data>)
        AS <alias for the source query>
    PIVOT
    (
        <aggregation function>(<column being aggregated>)
    FOR
    [<column that contains the values that will become column headers>]
        IN ( [first pivoted column], [second pivoted column],
        ... [last pivoted column])
    ) AS <alias for the pivot table>
    <optional ORDER BY clause>;

检查此参考文献:Click Here

答案 3 :(得分:0)

您需要UNPIVOT

DECLARE @t TABLE
    (
      G CHAR(1) ,
      V1 INT ,
      V2 INT ,
      V3 INT
    )

INSERT  INTO @t
VALUES  ( 'A', 10, 10, 5 ),
        ( 'B', 12, 20, 25 ),
        ( 'C', 20, 40, 50 );
WITH    cte1
          AS ( SELECT   *
               FROM     @t
               WHERE    G = 'A'
             ),
        cte2
          AS ( SELECT   *
               FROM     @t
               WHERE    G = 'B'
             ),
        cte3
          AS ( SELECT   *
               FROM     @t
               WHERE    G = 'C'
             )
    SELECT  u1.v ,
            u1.a ,
            u2.b ,
            u3.c
    FROM    ( SELECT    *
              FROM      cte1 UNPIVOT( a FOR v IN ( [V1], [V2], [V3] ) ) u
            ) u1
            JOIN ( SELECT   *
                   FROM     cte2 UNPIVOT( b FOR v IN ( [V1], [V2], [V3] ) ) u
                 ) u2 ON u1.v = u2.v
            JOIN ( SELECT   *
                   FROM     cte3 UNPIVOT( c FOR v IN ( [V1], [V2], [V3] ) ) u
                 ) u3 ON u2.v = u3.v

输出:

v   a   b   c
V1  10  12  20
V2  10  20  40
V3  5   25  50