sql server - Comment transformer des colonnes Sql en lignes?

Translate

J'ai un problème très simple qui nécessite une solution très rapide et simple dans SQL Server 2005.

J'ai une table avec x colonnes. Je veux pouvoir sélectionner une ligne dans le tableau, puis transformer les colonnes en lignes.

TableA
Column1, Column2, Column3

Instruction SQL à ruturn

ResultA
Value of Column1
Value of Column2
Value of Column3

@Kevin:J'ai eu une recherche google sur le sujet, mais beaucoup d'exemples étaient trop complexes pour mon exemple,pouvez-vous aider davantage?

@Mario: La solution que je crée a 10 colonnes qui stockent les valeurs 0 à 6 et je dois déterminer combien de colonnes ont la valeur 3 ou plus. J'ai donc pensé à créer une requête pour transformer cela en lignes, puis à utiliser la table générée dans une sous-requête pour dire compter le nombre de lignes avec Colonne> = 3

This question and all comments follow the "Attribution Required."

Toutes les réponses

Kev
Translate

Vous devriez jeter un œil à la clause UNPIVOT.

Mise à jour1: GateKiller, étrangement, j'ai lu un article (sur quelque chose sans rapport) à ce sujet ce matin et j'essaie de me rafraîchir la mémoire là où je l'ai revu, j'avais aussi des exemples décents. Cela me reviendra, j'en suis sûr.

Update2: Je l'ai trouvé:http://weblogs.sqlteam.com/jeffs/archive/2008/04/23/unpivot.aspx

La source
Translate

Je devais faire ça pour un projet avant. L'une des principales difficultés que j'ai eues a été d'expliquer ce que j'essayais de faire à d'autres personnes. J'ai passé beaucoup de temps à essayer de faire cela en SQL, mais j'ai trouvé la fonction pivot terriblement inadéquate. Je ne me souviens pas de la raison exacte pour laquelle c'était, mais c'est trop simpliste pour la plupart des applications, et ce n'est pas complètement implémenté dans MS SQL 2000. J'ai fini par écrire une fonction pivot dans .NET. Je le posterai ici dans l'espoir que cela aide quelqu'un, un jour.

 ''' <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
La source
Translate

SYNDICATdevrait être votre ami:

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

mais ça peutêtre aussi ton ennemisur de grands ensembles de résultats.

La source
Translate

Si vous avez un ensemble fixe de colonnes et que vous savez ce qu'elles sont, vous pouvez essentiellement faire une série de sous-sélections

(SELECT Column1 AS ResultA FROM TableA) as R1

et rejoignez les sous-sélections. Tout cela en une seule requête.

La source
Mat
Translate

Je ne suis pas sûr de la syntaxe de SQL Server pour cela, mais dans MySQL, je le ferais

SELECT IDColumn, ( IF( Column1 >= 3, 1, 0 ) + IF( Column2 >= 3, 1, 0 ) + IF( Column3 >= 3, 1, 0 ) + ... [snip ] )
  AS NumberOfColumnsGreaterThanThree
FROM TableA;

EDIT: Une très (très) brève recherche sur Google me dit que leCASEdéclaration fait ce que je fais avec leIFdéclaration dans MySQL. Vous pouvez ou non utiliserle résultat Google que j'ai trouvé

EDIT SUPPLÉMENTAIRE: Je dois également souligner que ce n'est pas une réponse à votre question mais une solution alternative à votre problème réel.

La source
Raymond Lee
Translate
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;
La source