Как преобразовать столбцы SQL в строки?
У меня очень простая проблема, которая требует очень быстрого и простого решения в SQL Server 2005.
У меня есть таблица с x столбцами. Я хочу иметь возможность выбрать одну строку из таблицы, а затем преобразовать столбцы в строки.
TableA
Column1, Column2, Column3
Оператор SQL для ruturn
ResultA
Value of Column1
Value of Column2
Value of Column3
@Kevin: У меня был поиск в Google по этой теме, но многие примеры слишком сложны для моего примера. Можете ли вы помочь в дальнейшем?
@Mario: Решение, которое я создаю, имеет 10 столбцов, в которых хранятся значения от 0 до 6, и я должен определить, сколько столбцов имеют значение 3 или более. Поэтому я подумал о создании запроса, чтобы превратить это в строки, а затем использовать сгенерированную таблицу в подзапросе, чтобы сказать, подсчитать количество строк со столбцом> = 3
Ответов (6)6
Вам следует взглянуть на предложение UNPIVOT.
Update1: GateKiller, strangely enough I read an article (about something unrelated) about it this morning and I'm trying to jog my memory where I saw it again, had some decent looking examples too. It'll come back to me I'm sure.
Update2: Found it: http://weblogs.sqlteam.com/jeffs/archive/2008/04/23/unpivot.aspx
UNION должен быть вашим другом:
SELECT Column1 FROM table WHERE idColumn = 1
UNION ALL
SELECT Column2 FROM table WHERE idColumn = 1
UNION ALL
SELECT Column3 FROM table WHERE idColumn = 1
но он также может быть вашим противником при больших наборах результатов.
Раньше мне приходилось делать это для проекта. Одна из главных трудностей, с которой я столкнулся, заключалась в том, чтобы объяснять другим людям, что я пытаюсь сделать. Я потратил кучу времени, пытаясь сделать это в 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
Я не уверен в синтаксисе 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, которые я нашел
ДАЛЬНЕЙШЕЕ РЕДАКТИРОВАНИЕ: я также должен указать, что это не ответ на ваш вопрос, а альтернативное решение вашей реальной проблемы.