Sqlserver
 sql >> Base de données >  >> RDS >> Sqlserver

Transposer des lignes et des colonnes sans agrégat

Si vous allez appliquer le PIVOT fonction, vous devrez utiliser une fonction d'agrégation pour obtenir le résultat, mais vous voudrez également utiliser une fonction de fenêtrage comme row_number() pour générer une séquence unique pour chaque contact du compte.

Tout d'abord, vous interrogerez vos données comme :

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

Voir SQL Fiddle avec démo. Cela créera une nouvelle colonne avec la séquence unique :

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

Si vous avez un nombre limité de colonnes, vous pouvez coder en dur votre requête :

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;

Voir SQL Fiddle avec démo

Si vous avez un nombre inconnu de colonnes, alors vous devrez utiliser du SQL dynamique :

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;

Voir SQL Fiddle avec démo. Les deux vous donneront un résultat de :

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