Sqlserver
 sql >> Datenbank >  >> RDS >> Sqlserver

Wie man eine unbekannte Anzahl von Spalten und kein Aggregat in SQL Server dreht?

Während die Antwort von M.Ali Ihnen das Ergebnis liefert, würde ich, da Sie SQL Server 2012 verwenden, den name entpivotieren und address Spalten etwas anders, um das Endergebnis zu erhalten.

Da Sie SQL Server 2012 verwenden, können Sie CROSS APPLY verwenden mit VALUES um diese mehreren Spalten in mehrere Zeilen zu entpivotieren. Aber bevor Sie das tun, würde ich row_number() verwenden um die Gesamtzahl der neuen Spalten zu erhalten, die Sie haben werden.

Der Code zum "UNPIVOT" der Daten mit CROSS APPLY sieht folgendermaßen aus:

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);

Siehe SQL-Fiddle mit Demo. Dadurch werden Ihre Daten in ein ähnliches Format gebracht wie:

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

Sie haben jetzt eine einzelne Spalte COL mit all Ihren neuen Spaltennamen und den zugehörigen Werten befinden sich ebenfalls in einer einzigen Spalte. Die neuen Spaltennamen haben jetzt eine Zahl am Ende (1, 2, 3 usw.), basierend darauf, wie viele Einträge Sie insgesamt pro loanid haben . Jetzt können Sie PIVOT anwenden:

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;

Siehe SQL-Fiddle mit Demo. Schließlich, wenn Sie nicht wissen, wie viele Paare von Name und address Sie haben dann können Sie dynamisches SQL verwenden:

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;

Siehe SQL-Fiddle mit Demo. Beide Versionen liefern ein Ergebnis:

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