sql >> Databasteknik >  >> RDS >> Sqlserver

Hur konverterar man radvärden till kolumner med dynamiska kolumner?

Mitt förslag när du arbetar med PIVOT är att alltid skriva frågan först med värdena hårdkodade, sedan kan du enkelt konvertera frågan till en dynamisk lösning.

Eftersom du kommer att ha flera värden för columnC som kommer att konverteras till kolumner, då måste du titta på att använda row_number() fönsterfunktion för att generera en unik sekvens för varje columnc baserat på värdena för columnA och columnB .

Startpunkten för din fråga kommer att vara:

select [ColumnA],
  [ColumnB],
  [ColumnC],
  'SampleTitle'+
  cast(row_number() over(partition by columna, columnb
                          order by columnc) as varchar(10)) seq
from DataSource;

Se Demo. Den här frågan genererar listan med nya kolumnnamn SampleTitle1 osv:

| COLUMNA | COLUMNB | COLUMNC |          SEQ |
|---------|---------|---------|--------------|
|    5060 |    1006 |  100118 | SampleTitle1 |
|    5060 |    1006 |  100119 | SampleTitle2 |
|    5060 |    1006 |  100120 | SampleTitle3 |

Du kan sedan använda pivoten på columnC med de nya kolumnnamnen listade i seq :

select columnA, columnB, 
  SampleTitle1, SampleTitle2, SampleTitle3
from
(
   select [ColumnA],
    [ColumnB],
    [ColumnC],
    'SampleTitle'+
      cast(row_number() over(partition by columna, columnb
                              order by columnc) as varchar(10)) seq
   from DataSource
) d
pivot
(
  max(columnc)
  for seq in (SampleTitle1, SampleTitle2, SampleTitle3)
) piv;

Se SQL Fiddle with Demo.

När du har rätt logik kan du konvertera data till dynamisk SQL. Nyckeln här är att skapa listan med nya kolumnnamn. Jag använder vanligtvis FOR XML PATH för detta som liknar:

select STUFF((SELECT distinct ',' + QUOTENAME(seq) 
                from
                (
                  select 'SampleTitle'+
                    cast(row_number() over(partition by columna, columnb
                                            order by columnc) as varchar(10)) seq
                  from DataSource
                ) d
        FOR XML PATH(''), TYPE
        ).value('.', 'NVARCHAR(MAX)') 
    ,1,1,'')

Se Demo. När du har listan med kolumnnamn kommer du att generera din sql-sträng för att exekvera, den fullständiga koden kommer att vara:

DECLARE @cols AS NVARCHAR(MAX),
    @query  AS NVARCHAR(MAX)

select @cols = STUFF((SELECT distinct ',' + QUOTENAME(seq) 
                    from
                    (
                      select 'SampleTitle'+
                        cast(row_number() over(partition by columna, columnb
                                                order by columnc) as varchar(10)) seq
                      from DataSource
                    ) d
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

set @query = 'SELECT columnA, ColumnB,' + @cols + ' 
             from 
             (
               select [ColumnA],
                [ColumnB],
                [ColumnC],
                ''SampleTitle''+
                  cast(row_number() over(partition by columna, columnb
                                          order by columnc) as varchar(10)) seq
               from DataSource
            ) x
            pivot 
            (
                max(columnc)
                for seq in (' + @cols + ')
            ) p '

execute sp_executesql @query;

Se SQL Fiddle with Demo. Dessa ger ett resultat:

| COLUMNA | COLUMNB | SAMPLETITLE1 | SAMPLETITLE2 | SAMPLETITLE3 |
|---------|---------|--------------|--------------|--------------|
|    5060 |    1006 |       100118 |       100119 |       100120 |
|    5060 |    1007 |       100121 |       100122 |       (null) |
|    5060 |    1012 |       100123 |       (null) |       (null) |



  1. Hur man hämtar fältnamn från temporär tabell (SQL Server 2008)

  2. Hur man lägger till rankningspositioner för rader i SQL med RANK()

  3. Hur tar jag bort specifika rader i SQLite Database

  4. ORA-12514 TNS:listener känner för närvarande inte till tjänst som efterfrågas i anslutningsbeskrivningen