変換する列の数がわかっている場合は、 anUNPIVOT
と a の両方でこれを実現でき、静的バージョンを使用できます。PIVOT
select *
from
(
select id, customerid, name, address,
col + '_'+ cast(rn as varchar(10)) col,
value
from
(
select c.id, customerid, c.name, c.address,
t.contactname,
cast(t.contact as varchar(20)) contact,
cast(t.id as varchar(20)) contactid,
row_number() over(partition by customerid order by customerid) rn
from customers c
left join contacts t
on c.id = t.customerid
) x
unpivot
(
value
for col in (ContactName, Contact, ContactId)
) u
) x1
pivot
(
min(value)
for col in ([ContactId_1], [ContactName_1], [Contact_1],
[ContactId_2], [ContactName_2], [Contact_2])
) p
SQL Fiddle with Demoを参照してください
ただし、レコードに含まれる連絡先の数がわからない場合は、動的 SQL を使用してこれを行います。
DECLARE @colsPivot AS NVARCHAR(MAX),
@colsUnpivot AS NVARCHAR(MAX),
@query AS NVARCHAR(MAX)
SET @colsUnPivot = stuff((select ','
+quotename(case when C.name = 'id' then'ContactId' else c.name end)
from sys.columns as C
where C.object_id = object_id('contacts') and
C.name <> 'CustomerId'
for xml path('')), 1, 1, '')
SET @colsPivot
= stuff((select ','+quotename(case when C.name = 'id' then'ContactId' else c.name end + '_' + cast(rn as varchar(10)))
from sys.columns as C
cross apply
(
select row_number() over(partition by customerid order by customerid) rn
from customers c
left join contacts t
on c.id = t.customerid
) x
where C.object_id = object_id('contacts') and
C.name <> 'CustomerId'
group by name, rn
order by rn
for xml path('')), 1, 1, '')
set @query
= '
select *
from
(
select id, customerid, name, address,
col + ''_''+ cast(rn as varchar(10)) col,
value
from
(
select c.id, customerid, c.name, c.address,
t.contactname,
cast(t.contact as varchar(20)) contact,
cast(t.id as varchar(20)) contactid,
row_number() over(partition by customerid order by customerid) rn
from customers c
left join contacts t
on c.id = t.customerid
) x1
unpivot
(
value
for col in (' + @colsUnPivot + ')
) unpvt
) x2
pivot
(
min(value)
for col in(' + @colsPivot +')
)p'
execute(@query)
SQL Fiddle with Demoを参照してください
どちらも同じ結果になります。