Pivot và Unpivot trong SQL Server và DW

Giả sử ta muốn tính tổng số tiền của mổi sản phẩm theo tháng dựa vào số liệu sau:

OrderIDProductIDNameValueQualityPostingDate
ORD0011Product A9000122019-11-11
ORD0011Product A5000022019-11-11
ORD0012Product B800000052019-10-10
ORD0023Product C900000012019-12-12
ORD0021Product A9000162019-09-09

Sau khi query thì được kết quả như sau:

ProductIDName123456789101112
1Product A0000000014400002080000
2Product B000000000000
3Product C000000000009000000

Một số câu query về PIVOT và UNPIVOT cho câu hỏi trên

-- drop table #yourtable2
-- drop table #PIVOT_TABLE
DECLARE @json NVARCHAR(MAX) =   
N'[
    {
        "OrderID":"ORD001",
        "ProductID":1,
        "Name":"Product A",
        "Value":50000,
        "Quality": 2,
        "PostingDate": "2019-11-11"
    },
    {
        "OrderID":"ORD001",
        "ProductID":2,
        "Name":"Product B",
        "Value":8000000,
        "Quality": 5,
        "PostingDate": "2019-10-10"
    },
    {
        "OrderID":"ORD002",
        "ProductID":3,
        "Name":"Product C",
        "Value":9000000,
        "Quality": 1,
        "PostingDate": "2019-12-12"
    },
    {
        "OrderID":"ORD002",
        "ProductID":1,
        "Name":"Product A",
        "Value":9000,
        "Quality": 16,
        "PostingDate": "2019-09-09"
    }
]
';
SELECT * 
INTO #YourTable2
FROM  OPENJSON ( @json )  
WITH (   
    OrderID  varchar(8) '$.OrderID',  
    ProductID  int '$.ProductID',  
    [Name] varchar(200) '$.Name',  
    [Value] int '$.Value',
    [Quality] int '$.Quality',
    [PostingDate] DATETIME '$.PostingDate'
) 

INSERT into #YourTable2(OrderID,ProductID,[Name],[Value] ,[Quality],[PostingDate]) 
VALUES ('ORD001', 1, 'Product A', 9000, 12, '2019-11-11')


SELECT *
INTO #PIVOT_TABLE
FROM 
(
  SELECT  top 10 [ProductID], [Name], month( PostingDate) as [FMonth], sum([value] * [Quality] ) as Cost
    FROM #YourTable2
  group by [ProductID], [Name], month( PostingDate)
  
) AS [data]
PIVOT 
(
 SUM([Cost])
 FOR [FMonth] IN ([1], [2], [3], [4], [5], [6], [7], [8], [9], [10], [11], [12])
) AS [pivotTable]


select *, [value] * [Quality]  as Cost from #YourTable2 --where 

select * from #PIVOT_TABLE

-- Unpivot the table.  
SELECT [ProductID], [Name], FMonth, Cost 
FROM   
   (SELECT * 
   FROM #PIVOT_TABLE) p  
UNPIVOT  
   (Cost FOR FMonth IN ([1], [2], [3], [4], [5], [6], [7], [8], [9], [10], [11], [12])
) AS unpvt;  


drop table #yourtable2
drop table #PIVOT_TABLE