2013-04-05 54 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