sql >> Database >  >> RDS >> Sqlserver

Hoe rijwaarden converteren naar kolommen met dynamische kolommentelling?

Mijn suggestie wanneer u met PIVOT werkt, is om de query altijd eerst te schrijven met de waarden hardgecodeerd, waarna u de query eenvoudig kunt converteren naar een dynamische oplossing.

Aangezien u meerdere waarden van columnC . zult hebben dat zal worden geconverteerd naar kolommen, dan moet je kijken naar het gebruik van de row_number() vensterfunctie om een ​​unieke reeks te genereren voor elke columnc gebaseerd op de waarden van columnA en columnB .

Het startpunt voor uw vraag is:

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

Zie demo. Deze query genereert de lijst met nieuwe kolomnamen SampleTitle1 , enz:

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

U kunt dan de spil toepassen op columnC met de nieuwe kolomnamen vermeld in 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;

Zie SQL Fiddle met demo.

Zodra u de juiste logica heeft, kunt u de gegevens converteren naar dynamische SQL. De sleutel hier is het genereren van de lijst met nieuwe kolomnamen. Ik gebruik meestal FOR XML PATH hiervoor vergelijkbaar met:

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

Zie demo. Zodra u de lijst met kolomnamen hebt, genereert u uw sql-tekenreeks om uit te voeren, de volledige code is:

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;

Zie SQL Fiddle met demo. Deze geven een resultaat:

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



  1. Hoe de LIKE-operator werkt in MariaDB

  2. Meerdere INSERT-instructies versus enkele INSERT met meerdere VALUES

  3. IBM DB2 verbinden met IRI-software

  4. INSERT van 10 miljoen queries binnen 10 minuten in Oracle?