如何将Sql列转换为行?

我有一个非常简单的问题,它需要SQL Server 2005中一个非常快速和简单的解决方案。

我有一张x列的表格。我希望能够从表中选择一行,然后将这些列转换为行。

TableA
Column1, Column2, Column3

SQL语句到ruturn

ResultA
Value of Column1
Value of Column2
Value of Column3

@Kevin: I've had a Google search on the topic but alot of the example where overly complex for my example, are you able to help further?

@Mario: The solution I am creating has 10 columns which stores the values 0 to 6 and I must work out how many columns have the value 3 or more. So I thought about creating a query to turn that into rows and then using the generated table in a subquery to say count the number of rows with Column >= 3

0
额外 编辑
意见: 1
嗯......现在这是我从未尝试过的事情。我想到的解决方案太棘手,太难看了,我相信还有更优雅的东西。我也在UNPIVOT上进行了搜索,看起来这就是您应该走的路。我会把这个作为一个难题在接下来的日子里解决。
额外 作者 Mario Marinato,
额外 作者 Dalex,

5 答案

我之前必须为此做一个项目。我遇到的一个主要困难是解释了我想要对其他人做什么。我花了大量的时间试图在SQL中做到这一点,但我发现pivot函数可悲的不足。我不记得它的确切原因,但对于大多数应用程序来说这太简单了,并且它在MS SQL 2000中没有完全实现。我最终在.NET中编写了一个pivot函数。我会在这里张贴它,希望有一天能帮助别人。

 ''' 
''' Pivots a data table from rows to columns '''
 
    ''' 
The data table to be transformed
    ''' 
The name of the column that identifies each row
    ''' 
The name of the column with the values to be transformed from rows to columns
    ''' 
The name of the column with the values to pivot into the new columns
    ''' The transformed data table
    ''' 
    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
0
额外

我不确定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;

EDIT: A very (very) brief Google search tells me that the CASE statement does what I am doing with the IF statement in MySQL. You may or may not get use out of the Google result I found

进一步编辑:我也应该指出,这不是对你的问题的回答,而是你实际问题的替代解决方案。

0
额外

UNION should be your friend:

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

但它可以在大型结果集上也是你的敌人

0
额外

你应该看看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

0
额外

如果你有一组固定的列,并且你知道它们是什么,你基本上可以做一系列子选择

(SELECT Column1 AS ResultA FROM TableA) as R1

并加入子查询。所有这些都在一个查询中。

0
额外