我想弄清楚是否有可能以这些表为例来实现......
CustomersTable
Id | Name | Address
1 | John | Street A
2 | Paul | Street B
3 | Mary | Street C
ContactsTable
Id | CustomerId | ContactName | Contact
1 | 1 | Contact A | 123
2 | 1 | Contact B | 543
3 | 2 | Contact 1 | 678
4 | 3 | Contact A1 | 980
5 | 3 | Contact B2 | 521
得到这样的东西......
Id | Name | Address | ContactId_1 | ContactName_1 | Contact_1 | ContactId_2 | ContactName_2 | Contact_2
1 | John | Street A | 1 | Contact A | 123 | 2 | Contact B | 543
2 | Paul | Street B | 3 | Contact 1 | 678 | NULL | NULL | NULL
3 | Mary | Street C | 4 | Contact A1 | 980 | 5 | Contact B2 | 521
我们的想法是获得一个表格,其中联系人与其所属的每个客户并排。联系栏联系人当然将取决于每个客户的联系人数量。
这可以吗?怎么样?
提前致谢!
答案 0 :(得分:3)
如果您知道要转换的列数,则可以同时使用UNPIVOT
和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来执行此操作:
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)
两者都产生相同的结果。
答案 1 :(得分:1)
我首选的方法是加入和聚合。关键是为枢轴生成序列号:
select c.id, c.name, c.address,
max(case when seqqnum = 1 then con.ContactId end) as ContactId_1,
max(case when seqqnum = 1 then con.ContactName end) as ContactName_1,
max(case when seqqnum = 1 then con.Contact end) as Contact_1,
max(case when seqqnum = 2 then con.ContactId end) as ContactId_2,
max(case when seqqnum = 2 then con.ContactName end) as ContactName_2,
max(case when seqqnum = 2 then con.Contact end) as Contact_2
from customers c join
(select con.*,
row_number() over (partition by customerId order by id) as seqnum
from contacts con
) con
on c.id = con.customerid
group by c.id, c.name, c.address
您也可以通过一系列连接来完成此操作,但我更喜欢这种方法。