转置没有聚合的行和列
我有以下数据集
Account Contact 1 324324324 1 674323234 2 833343432 2 433243443 3 787655455 4 754327545 4 455435435 5 543544355 5 432455553 5 432433242 5 432432432
我想输出如下:
Account Contact1 Contact2 Contact3 Contact4 1 324324324 674323234 2 833343432 433243443 3 787655455 4 754327545 455435435 5 543544355 432455553 432433242 432432432
问题是我有一个未定额的帐户和未定的数量的联系人
如果您要应用PIVOT
函数,您将需要使用聚合函数来获取结果,但您也将需要使用像row_number()
这样的窗口函数来为帐户中的每个联系人生成唯一序列。
首先,您将查询您的数据类似于:
select account, contact, 'contact' + cast(row_number() over(partition by account order by contact) as varchar(10)) seq from yourtable
看演示与SQL小提琴 。 这将创build一个具有独特序列的新列:
| ACCOUNT | CONTACT | SEQ | |---------|-----------|----------| | 1 | 324324324 | contact1 | | 1 | 674323234 | contact2 |
如果列数有限,则可以对查询进行硬编码:
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;
看演示与SQL小提琴
如果您的列数量未知,那么您将不得不使用dynamicSQL:
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;
看演示与SQL小提琴 。 两者都会给你一个结果:
| 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 |
只是一个稍微不同的方式来生成dynamicPIVOT
:
DECLARE @c INT; SELECT TOP 1 @c = COUNT(*) FROM dbo.YourTable GROUP BY Account ORDER BY COUNT(*) DESC; DECLARE @dc1 NVARCHAR(MAX) = N'', @dc2 NVARCHAR(MAX) = N'', @sql NVARCHAR(MAX); SELECT @dc1 += ',Contact' + RTRIM(i), @dc2 += ',[Contact' + RTRIM(i) + ']' FROM (SELECT TOP (@c) i = number + 1 FROM master.dbo.spt_values WHERE type = N'P' ORDER BY number) AS x; SET @sql = N'SELECT Account ' + @dc1 + ' FROM (SELECT Account, Contact, rn = ''Contact'' + RTRIM(ROW_NUMBER() OVER (PARTITION BY Account ORDER BY Contact)) FROM dbo.YourTable) AS src PIVOT (MAX(Contact) FOR rn IN (' + STUFF(@dc2, 1, 1, '') + ')) AS p;'; EXEC sp_executesql @sql;
SQLiddle演示