結果を得るには、アンピボットとピボットの両方をデータに適用することをお勧めします。
UNPIVOT は、テーブルの列データを行に変換します。データのピボットが解除されたら、ピボットを適用できます。
SQL Server 2008+ を使用しているため、CROSS APPLY と VALUES 句を使用してピボットを解除できます。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);
デモを参照してください。これにより、データが次の形式に変換されます。
| 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 |