【问题标题】:How do I Transform Sql Columns into Rows?如何将 Sql 列转换为行?
【发布时间】:2008-08-06 14:36:56
【问题描述】:

我有一个非常简单的问题,需要在 SQL Server 2005 中快速简单地解决。

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

TableA
Column1, Column2, Column3

到 ruturn 的 SQL 语句

ResultA
Value of Column1
Value of Column2
Value of Column3

@Kevin:我已经在谷歌上搜索过这个主题,但是很多例子对于我的例子来说过于复杂,你能提供进一步的帮助吗?

@Mario:我正在创建的解决方案有 10 列存储值 0 到 6,我必须计算出有多少列具有值 3 或更多。因此,我考虑创建一个查询将其转换为行,然后在子查询中使用生成的表来计算 Column >= 3 的行数

【问题讨论】:

  • 嗯...现在这是我从未尝试过的东西。我想到的解决方案都太棘手也太丑陋了,我敢肯定还有更优雅的东西。我也在 UNPIVOT 上进行了搜索,看起来这就是你应该走的路。我会在接下来的几天里把这个当作一个谜题来解决。

标签: sql-server sql-server-2005


【解决方案1】:

你应该看看 UNPIVOT 子句。

Update1:GateKiller,奇怪的是我今天早上读了一篇关于它的文章(关于一些无关的东西),我试图在我再次看到它的地方慢跑记忆,也有一些看起来不错的例子.我相信它会回到我身边的。

Update2:找到它:http://weblogs.sqlteam.com/jeffs/archive/2008/04/23/unpivot.aspx

【讨论】:

    【解决方案2】:

    我以前必须为一个项目这样做。我遇到的主要困难之一是向其他人解释我想做什么。我花了很多时间尝试在 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
    

    【讨论】:

      【解决方案3】:

      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
      

      但它可以also be your foe 处理大型结果集。

      【讨论】:

        【解决方案4】:

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

        (SELECT Column1 AS ResultA FROM TableA) as R1

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

        【讨论】:

          【解决方案5】:

          我不确定 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 语句与我在 MySQL 中使用 IF 语句所做的一样。您可能会也可能不会使用the Google result I found

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

          【讨论】:

            【解决方案6】:
            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;
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2019-07-16
              • 2020-04-28
              • 2011-10-04
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多