SQL 열을 행으로 어떻게 변환합니까?
-
08-06-2019 - |
문제
SQL Server 2005에서 매우 빠르고 간단한 솔루션이 필요한 매우 간단한 문제가 있습니다.
x 열이 있는 테이블이 있습니다.테이블에서 하나의 행을 선택한 다음 열을 행으로 변환할 수 있기를 원합니다.
TableA
Column1, Column2, Column3
반환할 SQL 문
ResultA
Value of Column1
Value of Column2
Value of Column3
@케빈: 주제에 대해 Google 검색을 해보았지만 내 예에 비해 지나치게 복잡한 예가 많이 있습니다. 더 도와주실 수 있나요?
@마리오:내가 만들고 있는 솔루션에는 0부터 6까지의 값을 저장하는 10개의 열이 있으며, 3 이상의 값을 갖는 열 수를 계산해야 합니다.그래서 이를 행으로 변환하는 쿼리를 만든 다음 하위 쿼리에서 생성된 테이블을 사용하여 열 >= 3인 행 수를 계산하는 방법을 생각했습니다.
해결책
UNPIVOT 절을 살펴봐야 합니다.
업데이트 1:GateKiller, 이상하게도 오늘 아침에 그것에 관한 기사(관련되지 않은 내용에 대한)를 읽었고 기억을 되살리려고 노력 중입니다. 어디서 다시 보았는지 괜찮은 예도 있었습니다.그것은 나에게 다시 돌아올 것이라고 확신합니다.
업데이트2:그것을 발견: http://weblogs.sqlteam.com/jeffs/archive/2008/04/23/unpivot.aspx
다른 팁
이전에 프로젝트를 위해 이 작업을 수행해야 했습니다.제가 겪었던 가장 큰 어려움 중 하나는 제가 하려는 일을 다른 사람들에게 설명하는 것이었습니다.나는 SQL에서 이 작업을 수행하려고 많은 시간을 보냈지만 피벗 기능이 한심할 정도로 부적절하다는 것을 알았습니다.정확한 이유는 기억나지 않지만 대부분의 응용 프로그램에서는 너무 단순하며 MS SQL 2000에서는 완전히 구현되지 않습니다.결국 .NET에서 피벗 함수를 작성하게 되었습니다.언젠가 누군가에게 도움이 되길 바라며 여기에 게시하겠습니다.
''' <summary>
''' Pivots a data table from rows to columns
''' </summary>
''' <param name="dtOriginal">The data table to be transformed</param>
''' <param name="strKeyColumn">The name of the column that identifies each row</param>
''' <param name="strNameColumn">The name of the column with the values to be transformed from rows to columns</param>
''' <param name="strValueColumn">The name of the column with the values to pivot into the new columns</param>
''' <returns>The transformed data table</returns>
''' <remarks></remarks>
Public Shared Function PivotTable(ByVal dtOriginal As DataTable, ByVal strKeyColumn As String, ByVal strNameColumn As String, ByVal strValueColumn As String) As DataTable
Dim dtReturn As DataTable
Dim drReturn As DataRow
Dim strLastKey As String = String.Empty
Dim blnFirstRow As Boolean = True
' copy the original data table and remove the name and value columns
dtReturn = dtOriginal.Clone
dtReturn.Columns.Remove(strNameColumn)
dtReturn.Columns.Remove(strValueColumn)
' create a new row for the new data table
drReturn = dtReturn.NewRow
' Fill the new data table with data from the original table
For Each drOriginal As DataRow In dtOriginal.Rows
' Determine if a new row needs to be started
If drOriginal(strKeyColumn).ToString <> strLastKey Then
' If this is not the first row, the previous row needs to be added to the new data table
If Not blnFirstRow Then
dtReturn.Rows.Add(drReturn)
End If
blnFirstRow = False
drReturn = dtReturn.NewRow
' Add all non-pivot column values to the new row
For Each dcOriginal As DataColumn In dtOriginal.Columns
If dcOriginal.ColumnName <> strNameColumn AndAlso dcOriginal.ColumnName <> strValueColumn Then
drReturn(dcOriginal.ColumnName.ToLower) = drOriginal(dcOriginal.ColumnName.ToLower)
End If
Next
strLastKey = drOriginal(strKeyColumn).ToString
End If
' Add new columns if needed and then assign the pivot values to the proper column
If Not dtReturn.Columns.Contains(drOriginal(strNameColumn).ToString) Then
dtReturn.Columns.Add(drOriginal(strNameColumn).ToString, drOriginal(strValueColumn).GetType)
End If
drReturn(drOriginal(strNameColumn).ToString) = drOriginal(strValueColumn)
Next
' Add the final row to the new data table
dtReturn.Rows.Add(drReturn)
' Return the transformed data table
Return dtReturn
End Function
고정된 열 세트가 있고 그것이 무엇인지 알고 있는 경우 기본적으로 일련의 하위 선택을 수행할 수 있습니다.
(SELECT Column1 AS ResultA FROM TableA) as R1
하위 선택에 참여하세요.이 모든 것이 단일 쿼리로 이루어집니다.
이에 대한 SQL Server 구문은 확실하지 않지만 MySQL에서는 그렇게 할 것입니다.
SELECT IDColumn, ( IF( Column1 >= 3, 1, 0 ) + IF( Column2 >= 3, 1, 0 ) + IF( Column3 >= 3, 1, 0 ) + ... [snip ] )
AS NumberOfColumnsGreaterThanThree
FROM TableA;
편집하다:아주 (매우) 간단한 Google 검색을 통해 CASE
명령문은 내가 하는 일을 수행합니다. IF
MySQL의 명령문.당신은 사용할 수도 있고 사용하지 않을 수도 있습니다 내가 찾은 Google 검색결과
추가 편집:또한 이는 귀하의 질문에 대한 답변이 아니라 실제 문제에 대한 대안적인 솔루션이라는 점을 지적하고 싶습니다.
SELECT IDColumn,
NumberOfColumnsGreaterThanThree = (CASE WHEN Column1 >= 3 THEN 1 ELSE 0 END) +
(CASE WHEN Column2 >= 3 THEN 1 ELSE 0 END) +
(Case WHEN Column3 >= 3 THEN 1 ELSE 0 END)
FROM TableA;