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

SQL Server 2012 PIVOT sans agrégat

Il existe plusieurs façons de transformer les données. Certains utilisent une fonction d'agrégation et d'autres non. Mais même si vous faites pivoter une chaîne, vous pouvez toujours appliquer un agrégat.

Agréger avec CASE :

select name,
  max(case when category = 'A' then 'X' else '' end) CategoryA,
  max(case when category = 'B' then 'X' else '' end) CategoryB,
  max(case when category = 'C' then 'X' else '' end) CategoryC,
  max(case when category = 'D' then 'X' else '' end) CategoryD
from yourtable 
group by name

Voir SQL Fiddle avec démo

Pivot statique :

Vous pouvez toujours utiliser le PIVOT fonction pour transformer les données même si les valeurs sont des chaînes. Si vous avez un nombre connu de catégories, vous pouvez coder en dur la requête :

select name, 
  coalesce(A, '') CategoryA, 
  coalesce(B, '') CategoryB, 
  coalesce(C, '') CategoryC, 
  coalesce(C, '') CategoryD
from
(
  select name, category, 'X' flag
  from yourtable
) d
pivot
(
  max(flag)
  for category in (A, B, C, D)
) piv

Voir SQL Fiddle avec démo .

Pivot dynamique :

Si vous avez un nombre inconnu de catégories, vous pouvez utiliser le SQL dynamique :

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

select @cols = STUFF((SELECT  ',' + QUOTENAME(category) 
                    from yourtable
                    group by category
                    order by category
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

select @colsNull = STUFF((SELECT  ', coalesce(' + QUOTENAME(category)+', '''') as '+QUOTENAME('Category'+category)
                    from yourtable
                    group by category
                    order by category
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')


set @query = 'SELECT name, ' + @colsNull + ' 
              from 
             (
                select name, category, ''X'' flag
                from yourtable
            ) x
            pivot 
            (
                max(flag)
                for category in (' + @cols + ')
            ) p '

execute(@query)

Voir SQL Fiddle avec démo .

Jointures multiples :

select c1.name,
  case when c1.category is not null then 'X' else '' end as CategoryA,
  case when c2.category is not null then 'X' else '' end as CategoryB,
  case when c3.category is not null then 'X' else '' end as CategoryC,
  case when c4.category is not null then 'X' else '' end as CategoryD
from yourtable c1
left join yourtable c2
  on c1.name = c2.name
  and c2.category = 'B'
left join yourtable c3
  on c1.name = c3.name
  and c3.category = 'C'
left join yourtable c4
  on c1.name = c4.name
  and c4.category = 'D'
where c1.category = 'A'

Voir SQL Fiddle avec démo

Toutes les requêtes donneront le résultat :

| NAME | CATEGORYA | CATEGORYB | CATEGORYC | CATEGORYD |
--------------------------------------------------------
|  Joe |         X |         X |           |         X |
| Mary |         X |           |         X |         X |