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

Zeilen und Spalten ohne Aggregat transponieren

Wenn Sie den PIVOT anwenden Funktion, müssen Sie eine Aggregatfunktion verwenden, um das Ergebnis zu erhalten, aber Sie sollten auch eine Fensterfunktion wie row_number() verwenden um eine eindeutige Sequenz für jeden Kontakt im Konto zu generieren.

Zuerst werden Sie Ihre Daten ähnlich wie folgt abfragen:

select account, contact,
  'contact'
    + cast(row_number() over(partition by account
                              order by contact) as varchar(10)) seq
from yourtable

Siehe SQL-Fiddle mit Demo. Dadurch wird eine neue Spalte mit der eindeutigen Sequenz erstellt:

| ACCOUNT |   CONTACT |      SEQ |
|---------|-----------|----------|
|       1 | 324324324 | contact1 |
|       1 | 674323234 | contact2 |

Wenn Sie nur über eine begrenzte Anzahl von Spalten verfügen, können Sie Ihre Abfrage fest codieren:

select account,
  contact1, contact2, contact3, contact4
from 
(
  select account, contact,
    'contact'
      + cast(row_number() over(partition by account
                                order by contact) as varchar(10)) seq
  from yourtable
) d
pivot
(
  max(contact)
  for seq in (contact1, contact2, contact3, contact4)
) piv;

Siehe SQL Fiddle mit Demo

Wenn Sie eine unbekannte Anzahl von Spalten haben, müssen Sie dynamisches SQL verwenden:

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

select @cols = STUFF((SELECT ',' + QUOTENAME(seq) 
                    from
                    (
                      select 'contact'
                              + cast(row_number() over(partition by account
                                                        order by contact) as varchar(10)) seq
                      from yourtable
                    ) d
                    group by seq
                    order by seq
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

set @query = 'SELECT account, ' + @cols + ' 
            from 
            (
                select account, contact,
                  ''contact''
                    + cast(row_number() over(partition by account
                                              order by contact) as varchar(10)) seq
                from yourtable
            ) x
            pivot 
            (
                max(contact)
                for seq in (' + @cols + ')
            ) p '

execute sp_executesql @query;

Siehe SQL-Fiddle mit Demo. Beide geben Ihnen folgendes Ergebnis:

| ACCOUNT |  CONTACT1 |  CONTACT2 |  CONTACT3 |  CONTACT4 |
|---------|-----------|-----------|-----------|-----------|
|       1 | 324324324 | 674323234 |    (null) |    (null) |
|       2 | 433243443 | 833343432 |    (null) |    (null) |
|       3 | 787655455 |    (null) |    (null) |    (null) |
|       4 | 455435435 | 754327545 |    (null) |    (null) |
|       5 | 432432432 | 432433242 | 432455553 | 543544355 |