Hoe transformeer ek SQL-kolomme in rye?
-
08-06-2019 - |
Vra
Ek het 'n baie eenvoudige probleem wat 'n baie vinnige en eenvoudige oplossing in SQL Server 2005 vereis.
Ek het 'n tabel met x kolomme.Ek wil een ry uit die tabel kan kies en dan die kolomme in rye omskep.
TableA
Column1, Column2, Column3
SQL-stelling om te ruturn
ResultA
Value of Column1
Value of Column2
Value of Column3
@Kevin: Ek het 'n Google-soektog oor die onderwerp gehad, maar baie van die voorbeelde was te kompleks vir my voorbeeld, kan jy verder help?
@Mario:Die oplossing wat ek skep het 10 kolomme wat die waardes 0 tot 6 stoor en ek moet uitwerk hoeveel kolomme die waarde 3 of meer het.Ek het dus daaraan gedink om 'n navraag te skep om dit in rye te verander en dan die gegenereerde tabel in 'n subnavraag te gebruik om te sê tel die aantal rye met Kolom >= 3
Oplossing
U moet na die UNPIVOT-klousule kyk.
Opdatering 1:GateKiller, vreemd genoeg het ek vanoggend 'n artikel (oor iets wat nie verband hou nie) daaroor gelees en ek probeer my geheue draf waar ek dit weer gesien het, het ook 'n paar ordentlike voorbeelde gehad.Dit sal na my toe terugkom, ek is seker.
Opdatering 2:Het dit gekry: http://weblogs.sqlteam.com/jeffs/archive/2008/04/23/unpivot.aspx
Ander wenke
Ek moes dit voorheen vir 'n projek doen.Een van die groot probleme wat ek gehad het, was om aan ander mense te verduidelik wat ek probeer doen het.Ek het baie tyd spandeer om dit in SQL te probeer doen, maar ek het gevind dat die spilpuntfunksie ongelukkig onvoldoende was.Ek onthou nie die presiese rede hoekom dit was nie, maar dit is te simplisties vir die meeste toepassings, en dit is nie volledig in MS SQL 2000 geïmplementeer nie.Ek het uiteindelik 'n spilfunksie in .NET geskryf.Ek sal dit hier plaas in die hoop dat dit iemand help, eendag.
''' <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
UNIE moet jou vriend wees:
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
maar dit kan wees ook jou vyand op groot resultatestelle.
As jy 'n vaste stel kolomme het en jy weet wat hulle is, kan jy basies 'n reeks subseleksies doen
(SELECT Column1 AS ResultA FROM TableA) as R1
en sluit aan by die subkies.Dit alles in 'n enkele navraag.
Ek is nie seker van die SQL Server-sintaksis hiervoor nie, maar in MySQL sou ek dit doen
SELECT IDColumn, ( IF( Column1 >= 3, 1, 0 ) + IF( Column2 >= 3, 1, 0 ) + IF( Column3 >= 3, 1, 0 ) + ... [snip ] )
AS NumberOfColumnsGreaterThanThree
FROM TableA;
EDIT:'n Baie (baie) kort Google-soektog vertel my dat die CASE
stelling doen wat ek doen met die IF
stelling in MySQL.Jy kan of mag nie gebruik maak van die Google-resultaat wat ek gevind het
VERDERE EDIT:Ek moet ook daarop wys dat dit nie 'n antwoord op jou vraag is nie, maar 'n alternatiewe oplossing vir jou werklike probleem.
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;