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

lignes en colonnes

Pour ce type de données, vous devrez implémenter à la fois l'UNPIVOT puis le PIVOT fonctions de SQL Server. Le UNPIVOT prend vos données de plusieurs colonnes et les place dans deux colonnes, puis vous appliquez le PIVOT pour retransformer les données en colonnes.

Si vous connaissez toutes les valeurs que vous souhaitez transformer, vous pouvez les coder en dur, comme ceci :

select *
from
(
  select value, col+'_'+cast(rn as varchar(10)) col
  from
  (
    select nvrchildname,
      nvrgender,
      convert(varchar(10), dttchildDOB, 120) dttchildDOB,
      occupation,
      row_number() over(partition by intsid order by intCHID) rn
    from tblHRIS_ChildDetails
    where intsid = 463
  ) src
  unpivot
  (
    value 
    for col in (nvrchildname, nvrgender, dttchildDOB, occupation)
  ) unpiv
) src1
pivot
(
  max(value)
  for col in ([nvrchildname_1], [nvrgender_1], 
              [dttchildDOB_1], [occupation_1], 
              [nvrchildname_2], [nvrgender_2], 
              [dttchildDOB_2], [occupation_2]) 
) piv

Voir SQL Fiddle avec démo

Maintenant, si vous avez un nombre inconnu de valeurs à transformer, vous pouvez utiliser le SQL dynamique pour cela :

DECLARE @colsUnpivot AS NVARCHAR(MAX),
    @query  AS NVARCHAR(MAX),
    @colsPivot as  NVARCHAR(MAX)

select @colsUnpivot = stuff((select ','+quotename(C.name)
         from sys.columns as C
         where C.object_id = object_id('tblHRIS_ChildDetails') and
               C.name not in ('intCHID', 'intsid')
         for xml path('')), 1, 1, '')

select @colsPivot = STUFF((SELECT  ',' 
                      + quotename(c.name 
                         +'_'+ cast(t.rn as varchar(10)))
                    from 
                    (
                      select row_number() over(partition by intsid order by intCHID) rn
                      from tblHRIS_ChildDetails
                    ) t
                    cross apply sys.columns as C
                   where C.object_id = object_id('tblHRIS_ChildDetails') and
                         C.name not in ('intCHID', 'intsid')
                   group by c.name, t.rn
                   order by t.rn
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

set @query 
  = 'select *
      from
      (
        select col+''_''+cast(rn as varchar(10)) col, value
        from 
        (
          select nvrchildname,
            nvrgender,
            convert(varchar(10), dttchildDOB, 120) dttchildDOB,
            occupation,
            row_number() over(partition by intsid order by intCHID) rn
          from tblHRIS_ChildDetails
          where intsid = 463
        ) x
        unpivot
        (
          value
          for col in ('+ @colsunpivot +')
        ) u
      ) x1
      pivot
      (
        max(value)
        for col in  ('+ @colspivot +')
      ) p'

exec(@query)

Voir SQL Fiddle avec démo

Le résultat des deux requêtes est :

| NVRCHILDNAME_1 | NVRGENDER_1 | DTTCHILDDOB_1 | OCCUPATION_1 | NVRCHILDNAME_2 | NVRGENDER_2 | DTTCHILDDOB_2 | OCCUPATION_2 |
-----------------------------------------------------------------------------------------------------------------------------
|             SK |      Female |    2001-12-11 |     Studying |             SM |        Male |    2007-10-08 |      Student |