Programming/Microsoft SQL Server
1. Pivot

Pivot은 세로로 나열된 Table의 행(Row)을 가로열(Column)로 표시하는 것을 말합니다. 먼저 Pivot을 해보기 이전에 피벗되지 않은 상태로 Table을 조회하여 보도록 하겠습니다.

Select * From Sales.SalesPerson


위에서 조회한 Sales.SalesPerson Table에서 TerritoryID별로 Bonus의 합계를 구한 결과를 Pivot하여 가로로 표시하도록 하려면 다음과 같이 구현할 수 있습니다.

Select [1], [2], [3], [4], [5], [6], [7], [8], [9], [10]
From (Select TerritoryID, Bonus From Sales.SalesPerson) As PivoTable
Pivot (Sum(Bonus) For TerritoryID In ([1], [2], [3], [4], [5], [6], [7], [8], [9], [10])) As APivoRtn


Pivot은 먼저 Select구문에 가로로 표시할 열을 []를 통해 줍니다. (Table의 특정 열값을 가로로 표시할 수 있도록 조회하는 것이기 때문에 가로로 표시될때의 이름은 조회하고자 하는 값 중에 존재하는 이름으로 지정해야 합니다.  따라서 위 Pivot문에서 Pivot할때는 TerritoryID 열값이 1~10까지 존재(null 제외)하였으므로 열 이름을 1~10까지 지정해 준것입니다.)

Select [1], [2], [3], [4], [5], [6], [7], [8], [9], [10]

그 다음 From을 통해 실제 데이터를 조회할 Table을 지정합니다. (여기서는 Sales.SalesPerson Table에서 TerritoryID와 Bonus열만 조회하면 되므로 하위쿼리를 통해 이 두개의 열만 조회하도록 하였습니다.)
TerritoryID열은 가로로 표시할 열이며 Bonus열은 실제 데이터를 표시할 열에 해당합니다.

From (Select TerritoryID, Bonus From Sales.SalesPerson) As PivoTable

마지막으로 Pivot을 통해 표시할 데이터와 가로열을 지정하면 Pivot 구문이 완성됩니다.

2. Case문을 통한 Pivot

Case문을 사용하면 Pivot과 비슷한 결과를 얻으실 수 있습니다.
이전 Pivot한것과 비교해 보시기 바랍니다.

Select [1], [2], [3], [4], [5], [6], [7], [8], [9], [10]
From (Select TerritoryID, Bonus From Sales.SalesPerson) As PivoTable
Pivot (Sum(Bonus) For TerritoryID In ([1], [2], [3], [4], [5], [6], [7], [8], [9], [10])) As APivoRtn

Select Sum(Case TerritoryID When 1 Then Bonus Else 0 End) As [1],
 Sum(Case TerritoryID When 2 Then Bonus Else 0 End) As [2],
 Sum(Case TerritoryID When 3 Then Bonus Else 0 End) As [3],
 Sum(Case TerritoryID When 4 Then Bonus Else 0 End) As [4],
 Sum(Case TerritoryID When 5 Then Bonus Else 0 End) As [5],
 Sum(Case TerritoryID When 6 Then Bonus Else 0 End) As [6],
 Sum(Case TerritoryID When 7 Then Bonus Else 0 End) As [7],
 Sum(Case TerritoryID When 8 Then Bonus Else 0 End) As [8],
 Sum(Case TerritoryID When 9 Then Bonus Else 0 End) As [9],
 Sum(Case TerritoryID When 10 Then Bonus Else 0 End) As [10]
From Sales.SalesPerson


Case문에서는 데이터 조회시 TerritoryID값이 각각에 해당하는 경우(1부터 10까지) 그에 맞는 Bouns열의 값을 Sum하여 표시하도록 하고 있습니다.

이 Case문을 이용한 방법은 실제 Pivot문을 사용해 Pivot하는 것보다 더 많이 쓰이고 있는 방법이기도 합니다. 또한 Pivot문을 통한 Table조회시에는 Data를 표시할때 해당 값에 포함되지 않는 경우 null로 표시됩니다. Null대신에 다른 값으로 표시하려고 해도 Pivot안에서는 이를 대체할 마땅한 대안이 없는 것입니다.

만약 Pivot 문에서 null 대신 다른 값을 표시하려면 ISNULL([01], 0) AS [01] 처럼 처리합니다. null 이라면 0이 대신 표시되는데 0대신 다른 원하는 값이 있으면 그것으로 대체할 수 있습니다.
- sqlpivotinpivot 님

Select WorkOrderID, [772], [725], [726], [729]
From (Select WorkOrderID, ProductID, OrderQty From Production.WorkOrder Where WorkOrderID <= 5) As PvtTable
Pivot (Sum(OrderQty) For ProductID In ([772], [725], [726], [729])) As PvtReturn


하지만 Case문을 이용하면 Else절에 의해 Null대신 Else로 지정된 데이터로 치환하여 표시할 수 있습니다.

Select WorkOrderID,
 Sum(Case ProductID When 772 Then OrderQty Else 0 End) As [772],
 Sum(Case ProductID When 725 Then OrderQty Else 0 End) As [725],
 Sum(Case ProductID When 726 Then OrderQty Else 0 End) As [726],
 Sum(Case ProductID When 729 Then OrderQty Else 0 End) As [729]
From Production.WorkOrder
Where WorkOrderID <= 5
Group By WorkOrderID


3. unPivot

Pivot이 가로열로 표시되도록 하는 것이라면 unPivot은 가로표시된 것을 다시 세로로 표시할 수 있도록 해줍니다. unPivot을 Test하기 위해 Pivot된 데이터를 임시 테이블에 저장한 후 임시 테이블에서 unPivot을 구현해보도록 하겠습니다.

Select [1], [2], [3], [4], [5], [6], [7], [8], [9], [10]
Into #Temp
From (Select TerritoryID, Bonus From Sales.SalesPerson) As PivoTable
Pivot (Sum(Bonus) For TerritoryID In ([1], [2], [3], [4], [5], [6], [7], [8], [9], [10])) As APivoRtn

Select * From #Temp


unPivot을 하기위해서는 먼저 세로로 표시할 열 이름을 지정해 줘야 합니다.(이때 열 이름은 사용자임의대로 지정합니다.)
그다음 unPivot을 통해 해당 열에 표시할 데이터를 지정해 주면 되는데 Pivot할때와 반대로 위에서 지정한 열 이름에 Pivot할때의 열 이름을 그대로 For를 통해 다시 구현하면 됩니다.

Select TerritoryID, Bonus
From #Temp
UnPivot (Bonus For TerritoryID In ([1], [2], [3], [4], [5], [6], [7], [8], [9], [10])) As UnPivoRtn

6 0