将行转换为SQL Server中的列

时间:2013-09-25 12:05:49

标签: sql sql-server-2005 pivot unpivot

我有一个带有以下数据的SQL Server表

SKU || Value || Volume 
 AB      2        3
 AB      2        2
 BB      1        3  

预期产出:

AB(value) || BB (VALUE) || AB(Volume) || BB (Volume)     
   4             1              5           3

注意:Sku列数据将是动态的

由于

2 个答案:

答案 0 :(得分:3)

您可以使用PIVOT功能获得结果。由于您将拥有未知数量的SKU值,我将首先编写查询的硬编码版本,然后将其转换为动态SQL。

由于您有两列要从valuevolume转移数据,因此我首先将这两列拆分为多行,然后应用PIVOT函数。 unpivot语法可以使用UNPIVOT函数或CROSS APPLY:

select col = t.sku+'_'+ c.col, 
  c.val
from yourtable t
cross apply
(
  select 'value', value union all
  select 'volume', volume
) c (col, val)

Demo。这给出了一个结果:

|       COL | VAL |
|  AB_value |   2 |
| AB_volume |   3 |
|  AB_value |   2 |
| AB_volume |   2 |
|  BB_value |   1 |
| BB_volume |   3 |

将数据转换为与此类似的格式后,即可应用PIVOT:

select AB_Value, BB_Value, AB_Volume, BB_Volume
from
(
  select col = t.sku+'_'+ c.col, 
    c.val
  from yourtable t
  cross apply
  (
    select 'value', value union all
    select 'volume', volume
  ) c (col, val)
) d
pivot
(
  sum(val)
  for col in (AB_Value, BB_Value, AB_Volume, BB_Volume)
) piv;

SQL Fiddle with Demo。既然你将拥有未知数量的值,那么你将不得不使用动态SQL来生成你需要执行的SQL字符串:

DECLARE @cols AS NVARCHAR(MAX),
    @query  AS NVARCHAR(MAX)

select @cols = STUFF((SELECT ',' + QUOTENAME(sku+'_'+col) 
                    from yourtable
                    cross apply
                    (
                      select 'value', 1 union all
                      select 'volume', 2
                    ) c (col, so)
                    group by sku, so, col
                    order by so, sku
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')


set @query = 'SELECT ' + @cols + ' 
            from 
            (
              select col = t.sku+''_''+ c.col, 
                c.val
              from yourtable t
              cross apply
              (
                select ''value'', value union all
                select ''volume'', volume
              ) c (col, val)
            ) x
            pivot 
            (
                sum(val)
                for col in (' + @cols + ')
            ) p '

execute sp_executesql @query;

SQL Fiddle with Demo。两个版本都给出了结果:

| AB_VALUE | BB_VALUE | AB_VOLUME | BB_VOLUME |
|        4 |        1 |         5 |         3 |

答案 1 :(得分:0)

SQL Fiddle

MS SQL Server 2008架构设置

CREATE TABLE Table1
    ([SKU] varchar(2), [Value] int, [Volume] int)
;

INSERT INTO Table1
    ([SKU], [Value], [Volume])
VALUES
    ('AB', 2, 3),
    ('AB', 2, 2),
    ('BB', 1, 3)
;

查询1

DECLARE @colTable table(rownum int,columnName varchar(20),value int,volume int)
INSERT INTO @colTable SELECT row_number() over (ORDER BY SKU), SKU, 
                             SUM(Value), SUM(Volume) FROM Table1 GROUP BY SKU
DECLARE @query varchar(500)
DECLARE @i int, @max int
SET @i = 1
SET @max = (SELECT count(*) FROM @colTable)
SET @query = 'select '
WHILE @i <= @max
BEGIN
    IF @i > 1 SET @query = @query + ','
    SET @query = @query + 
             (SELECT cast(value as varchar) FROM @colTable WHERE rownum = @i) + 
             ' AS "' + 
             (SELECT columnName FROM @colTable WHERE rownum = @i) + '(Value)"'
    SET @query = @query + ','
    SET @query = @query + 
             (SELECT cast(volume as varchar) FROM @colTable WHERE rownum = @i) + 
             ' AS "' + 
             (SELECT columnName FROM @colTable WHERE rownum = @i) + '(Volume)"'
    SET @i = @i + 1
END
exec(@query)

<强> Results

| AB(VALUE) | AB(VOLUME) | BB(VALUE) | BB(VOLUME) |
|-----------|------------|-----------|------------|
|         4 |          5 |         1 |          3 |