sql >> Databasteknik >  >> RDS >> Sqlserver

Hur pivoterar man okänt antal kolumner och inget aggregat i SQL Server?

Medan M.Alis svar kommer att ge dig resultatet, eftersom du använder SQL Server 2012 skulle jag avpivotera name och address kolumner något annorlunda för att få det slutliga resultatet.

Eftersom du använder SQL Server 2012 kan du använda CROSS APPLY med VALUES för att avpivotera dessa flera kolumner till flera rader. Men innan du gör det skulle jag använda row_number() för att få det totala antalet nya kolumner du kommer att ha.

Koden för att "UNPIVOT" data med hjälp av CROSS APPLY ser ut så här:

select d.loanid, 
  col = c.col + cast(seq as varchar(10)),
  c.value
from
(
  select loanid, name, address,
    row_number() over(partition by loanid
                      order by loanid) seq
  from yourtable
) d
cross apply
(
  values
    ('name', name),
    ('address', address)
) c(col, value);

Se SQL Fiddle with Demo. Detta kommer att få dina data till ett format som liknar:

| LOANID |      COL |    VALUE |
|--------|----------|----------|
|      1 |    name1 |     John |
|      1 | address1 | New York |
|      1 |    name2 |     Carl |
|      1 | address2 | New York |
|      1 |    name3 |    Henry |
|      1 | address3 |   Boston |

Du har nu en enda kolumn COL med alla dina nya kolumnnamn och de associerade värdena finns också i en enda kolumn. De nya kolumnnamnen har nu ett nummer i slutet (1, 2, 3, etc) baserat på hur många totala poster du har per loanid . Nu kan du använda PIVOT:

select loanid,
  name1, address1, name2, address2,
  name3, address3
from
(
  select d.loanid, 
    col = c.col + cast(seq as varchar(10)),
    c.value
  from
  (
    select loanid, name, address,
      row_number() over(partition by loanid
                        order by loanid) seq
    from yourtable
  ) d
  cross apply
  (
    values
      ('name', name),
      ('address', address)
  ) c(col, value)
) src
pivot
(
  max(value)
  for col in (name1, address1, name2, address2,
              name3, address3)
) piv;

Se SQL Fiddle with Demo. Slutligen om du inte vet hur många par Name och Address du har då kan du använda dynamisk SQL:

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

select @cols = STUFF((SELECT ',' + QUOTENAME(col+cast(seq as varchar(10))) 
                    from 
                    (
                      select row_number() over(partition by loanid
                                                order by loanid) seq
                      from yourtable
                    ) d
                    cross apply
                    (
                      select 'Name', 1 union all
                      select 'Address', 2
                    ) c (col, so)
                    group by seq, col, so
                    order by seq, so
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

set @query = 'SELECT loanid,' + @cols + ' 
            from 
            (
              select d.loanid, 
                col = c.col + cast(seq as varchar(10)),
                c.value
              from
              (
                select loanid, name, address,
                  row_number() over(partition by loanid
                                    order by loanid) seq
                from yourtable
              ) d
              cross apply
              (
                values
                  (''name'', name),
                  (''address'', address)
              ) c(col, value)
            ) x
            pivot 
            (
                max(value)
                for col in (' + @cols + ')
            ) p '

exec sp_executesql @query;

Se SQL Fiddle with Demo. Båda versionerna ger ett resultat:

| LOANID |  NAME1 | ADDRESS1 |  NAME2 | ADDRESS2 |  NAME3 | ADDRESS3 |
|--------|--------|----------|--------|----------|--------|----------|
|      1 |   John | New York |   Carl | New York |  Henry |   Boston |
|      2 | Robert |  Chicago | (null) |   (null) | (null) |   (null) |
|      3 | Joanne |       LA |  Chris |       LA | (null) |   (null) |


  1. Databas:Pipelined-funktioner

  2. MySQL-fel:nyckelspecifikation utan nyckellängd

  3. PostgreSQL 12:Implementering av K-Nearest Neighbor Space Partitioned Generalized Search Tree Index

  4. Rethink Flask – En enkel att göra-lista som drivs av Flask och RethinkDB