2013-09-25 134 views
0

我有一個SQL Server表具有以下數據轉換行到列在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列數據將是動態的

感謝

+0

您需要使用PIVOT。然而,你將要旋轉的列是動態的,所以我懷疑這將非常難以編程 –

+0

通過將列值轉換爲一個變量,然後我們可以將該變量傳遞給數據透視'選擇'+ @ cols +'從測試 PIVOT ( SUM([值])在[SKU] IN( '+ @ COLS +') )p ' –

回答

3

您可以使用PIVOT功能來獲得結果。由於您將有一個未知數SKU值,因此我會先編寫查詢的硬編碼版本,然後將其轉換爲動態SQL。

既然你有兩列,你想要從valuevolume樞紐數據,那麼我會首先將這兩列轉移到多行,然後應用PIVOT功能。該逆透視語法可以使用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 | 

一旦你的數據轉換成一種格式,類似於此,那麼你可以申請樞軸:

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 | 
+0

完美解決 –

+0

W00t W00t!回答問題比海灘更有趣。 – Kermit

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 |