Domanda

Ho un problema molto semplice che richiede una soluzione molto rapida e semplice in SQL Server 2005.

Ho una tabella con x colonne.Voglio essere in grado di selezionare una riga dalla tabella e quindi trasformare le colonne in righe.

TableA
Column1, Column2, Column3

Istruzione SQL da eseguire

ResultA
Value of Column1
Value of Column2
Value of Column3

@Kevin: Ho effettuato una ricerca su Google sull'argomento, ma molti esempi erano eccessivamente complessi per il mio esempio, puoi aiutare ulteriormente?

@Mario:La soluzione che sto creando ha 10 colonne che memorizzano i valori da 0 a 6 e devo capire quante colonne hanno il valore 3 o più.Quindi ho pensato di creare una query per trasformarla in righe e quindi utilizzare la tabella generata in una sottoquery per dire contare il numero di righe con Colonna >= 3

È stato utile?

Soluzione

Dovresti dare un'occhiata alla clausola UNPIVOT.

Aggiornamento1:GateKiller, stranamente ho letto un articolo (su qualcosa di non correlato) a riguardo stamattina e sto cercando di rinfrescare la mia memoria dove l'ho visto di nuovo, aveva anche alcuni esempi dall'aspetto decente.Mi tornerà in mente, ne sono sicuro.

Aggiornamento2:Trovato: http://weblogs.sqlteam.com/jeffs/archive/2008/04/23/unpivot.aspx

Altri suggerimenti

Dovevo farlo prima per un progetto.Una delle maggiori difficoltà che ho avuto è stata spiegare cosa stavo cercando di fare alle altre persone.Ho passato molto tempo a provare a farlo in SQL, ma ho trovato la funzione pivot tristemente inadeguata.Non ricordo il motivo esatto per cui lo era, ma è troppo semplicistico per la maggior parte delle applicazioni e non è completamente implementato in MS SQL 2000.Ho finito per scrivere una funzione pivot in .NET.Lo pubblicherò qui nella speranza che possa aiutare qualcuno, un giorno.

 ''' <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

UNIONE dovrebbe essere tuo amico:

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

ma può essere anche tuo nemico su insiemi di risultati di grandi dimensioni.

Se hai un set fisso di colonne e sai cosa sono, puoi sostanzialmente eseguire una serie di sottoselezione

(SELECT Column1 AS ResultA FROM TableA) as R1

e unisciti alle sottoselezionate.Tutto questo in un'unica query.

Non sono sicuro della sintassi di SQL Server per questo, ma in MySQL lo farei

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

MODIFICARE:Una ricerca molto (molto) breve su Google mi dice che the CASE istruzione fa quello che sto facendo con il file IF dichiarazione in MySQL.Potresti o meno abituarti il risultato di Google che ho trovato

ULTERIORE MODIFICA:Dovrei anche sottolineare che questa non è una risposta alla tua domanda ma una soluzione alternativa al tuo problema reale.

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;
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top