2013-04-05 84 views
0

我有一張這樣的桌子。表1.需要樞軸支持

Customer Product  Value Quantity Order Number 


Dave Product 1 15 1 154 
Dave Product 2 25 5 154 
Dave Product 3 45 4 15 
Rob  Product 2 222 33 233 

現在我想這一點,表2

Customer Product 1 Quantity Product 1 Value  Price per item (Value /Quantity) for Product 1  Product 2 Quantity Product 2 Value  Price per item (Value /Quantity) for Product 2  Product 3 Quantity Product 3 Value  Price per item (Value /Quantity) for Product 3 Order Number 

Dave 1 15 15 5 25 5 null null null 154 

Dave null null null null null Null 4 45 11.25 15 

Rob  null null null 33 222 6.727272727 null null null 233 

我曾想過一些支點,但不知道如何構建它。還產品的數量是不固定的並在表1中

+0

什麼版本的sql server? – Taryn 2013-04-05 10:07:02

+0

2008 SQL Server – 2013-04-05 10:07:43

+0

你想要標題說實際的產品名稱(汽車等),或者你想要一個通用的product1嗎? – Taryn 2013-04-05 10:15:41

回答

6

改變爲了得到的結果,我建議施加兩者逆透視樞軸到的數據。

UNPIVOT會將表格中的列數據轉換爲行。一旦數據未轉化,您可以應用數據透視表。

由於您使用的是SQL Server 2008+,因此可以使用帶有VALUES子句的CROSS APPLY來反轉。在2008年之前,您可以使用UNPIVOT功能。未轉發數據的代碼是:

select t.customer, 
    replace(t.product, ' ', '')+'_'+c.col piv_col, 
    c.val, 
    t.ordernumber 
from table1 t 
cross apply 
(
    values 
    ('value', cast(value as varchar(10))), 
    ('quantity', cast(quantity as varchar(10))), 
    ('PricePerUnit', cast((value/quantity) *1.0 as varchar(10))) 
) c (col, val); 

請參閱Demo。這將數據轉換成以下格式:

| CUSTOMER |    PIV_COL | VAL | ORDERNUMBER | 
--------------------------------------------------------- 
|  Dave |  Product1_value | 15 |   154 | 
|  Dave |  Product1_quantity | 1 |   154 | 
|  Dave | Product1_PricePerUnit | 15.0 |   154 | 
|  Dave |  Product2_value | 25 |   154 | 

你可以看到,對於Dave訂單154行已經變成了行,我已經創建了一個將用於樞軸(piv_col)新的列名。此列已將產品名稱與以前列標題(值,數量)的起始位置連接起來。

由於數據是在一行中,因此您可以輕鬆地將透視函數應用於數據。最後的代碼將是:

select customer, 
    Product1_quantity, Product1_value, Product1_PricePerUnit, 
    Product2_quantity, Product2_value, Product2_PricePerUnit, 
    Product3_quantity, Product3_value, Product3_PricePerUnit, 
    orderNumber 
from 
(
    select t.customer, 
    replace(t.product, ' ', '')+'_'+c.col piv_col, 
    c.val, 
    t.ordernumber 
    from table1 t 
    cross apply 
    (
    values 
     ('value', cast(value as varchar(10))), 
     ('quantity', cast(quantity as varchar(10))), 
     ('PricePerUnit', cast((value/quantity) *1.0 as varchar(10))) 
) c (col, val) 
) d 
pivot 
(
    max(val) 
    for piv_col in(Product1_quantity, Product1_value, Product1_PricePerUnit, 
       Product2_quantity, Product2_value, Product2_PricePerUnit, 
       Product3_quantity, Product3_value, Product3_PricePerUnit) 
) piv; 

SQL Fiddle with Demo

如果你有一個已知數量的產品,上面的工作很好,但如果沒有,那麼你將需要使用動態SQL。

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

select @cols = STUFF((SELECT ',' + QUOTENAME(replace(t.product, ' ', '')+'_'+c.col) 
        from Table1 t 
        cross apply 
        (
         values ('value', 1), ('quantity', 0),('PricePerUnit', 3) 
        ) c (col, so)  
        group by product, col, so 
        order by product, so 
      FOR XML PATH(''), TYPE 
      ).value('.', 'NVARCHAR(MAX)') 
     ,1,1,'') 

set @query = 'SELECT customer, ' + @cols + ', ordernumber 
       from 
       (
       select t.customer, 
        replace(t.product, '' '', '''')+''_''+c.col piv_col, 
        c.val, 
        t.ordernumber 
       from table1 t 
       cross apply 
       (
        values 
        (''value'', cast(value as varchar(10))), 
        (''quantity'', cast(quantity as varchar(10))), 
        (''PricePerUnit'', cast((value/quantity) *1.0 as varchar(10))) 
       ) c (col, val) 
      ) d 
       pivot 
       (
       max(val) 
       for piv_col in (' + @cols + ') 
      ) p ' 

execute(@query); 

請參閱SQL Fiddle with Demo。這些查詢給出結果:

| CUSTOMER | PRODUCT1_QUANTITY | PRODUCT1_VALUE | PRODUCT1_PRICEPERUNIT | PRODUCT2_QUANTITY | PRODUCT2_VALUE | PRODUCT2_PRICEPERUNIT | PRODUCT3_QUANTITY | PRODUCT3_VALUE | PRODUCT3_PRICEPERUNIT | ORDERNUMBER | 
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 
|  Dave |   (null) |   (null) |    (null) |   (null) |   (null) |    (null) |     4 |    45 |     11.0 |   15 | 
|  Dave |     1 |    15 |     15.0 |     5 |    25 |     5.0 |   (null) |   (null) |    (null) |   154 | 
|  Rob |   (null) |   (null) |    (null) |    33 |   222 |     6.0 |   (null) |   (null) |    (null) |   233 | 
+1

+1我只希望我可以多次投票。很好的答案.. !! – praveen 2013-04-05 10:55:02

+1

你在想我。哇 。謝謝 。 – 2013-04-05 11:02:44