具有相似列名的动态数据透视表
Dynamic pivot with similar column names
我正在寻找一种将不同数量的行转换为 sql server 2008 R2
中的列的方法。我在查询中创建了数据列 RANK
,因为最终我希望将透视列名称标记为 RANK
列中的值。然后,如果我能以某种方式 STUFF
将其他 3 个字段值一起合并到一个字段中,我将能够遍历后端语言中的行并适当地拆分字段结果。
这是当前的数据集:
我希望枢轴的最终结果产生这样的结果:
我还没有发现任何关于能够以这种 "dynamic" 方式旋转的信息。任何帮助将不胜感激。
正如我上面提到的,您需要区分每个 Rank
值。您已经说过这是一个计算值,您可以在每个值的末尾添加一个数字。添加该数字后,您仍然需要对其进行旋转。
首先看到这一点的最简单方法是先编写查询的硬编码版本。
示例数据:
create table yourdata
(
id int,
code varchar(50),
created datetime,
[rank] varchar(50)
);
insert into yourdata
select 285856, 'J7609', '2015-01-19', 'Principle' union all
select 285856, 'J7613', '2015-01-19', 'Other' union all
select 285856, 'J0456', '2015-01-19', 'Other' union all
select 285856, 'J0694', '2015-01-19', 'Other' union all
select 285856, 'J1885', '2015-01-19', 'Other' union all
select 285856, 'J2060', '2015-01-19', 'Other' union all
select 285856, 'J2930', '2015-01-19', 'Other';
静态查询:
select Principle_1, Other_1,
Other_2, Other_3, Other_4,
Other_5, Other_6
from
(
-- using row_number to get unique id for each rank
select
data = cast(id as varchar(10)) +' | '+ code +' | '+ convert(varchar(10), created, 112),
[rank] = [rank] + '_' +cast(row_number() over(partition by id, [rank]
order by id) as varchar(10))
from yourdata
) d
pivot
(
max(data)
for [rank] in (Principle_1, Other_1, Other_2, Other_3, Other_4,
Other_5, Other_6)
) p;
现在要执行此动态操作,您将使用列名创建一个 sql 字符串,然后执行该字符串:
DECLARE @cols AS NVARCHAR(MAX),
@query AS NVARCHAR(MAX)
select @cols = STUFF((SELECT ',' + QUOTENAME([rank] + '_' +cast(rn as varchar(10)))
from
(
select [rank],
rn = row_number() over(partition by id, [rank]
order by id)
from yourdata
) d
group by [rank], rn
order by rn, [rank] desc
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set @query = 'SELECT ' + @cols + '
from
(
select
data = cast(id as varchar(10)) +'' | ''+ code +'' | ''+ convert(varchar(10), created, 112),
[rank] = [rank] + ''_'' +cast(row_number() over(partition by id, [rank]
order by id) as varchar(10))
from yourdata
) x
pivot
(
max(data)
for [rank] in (' + @cols + ')
) p '
exec sp_executesql @query;
这会得到一个结果:
+---------------------------+---------------------------+---------------------------+---------------------------+---------------------------+---------------------------+---------------------------+
| Principle_1 | Other_1 | Other_2 | Other_3 | Other_4 | Other_5 | Other_6 |
+---------------------------+---------------------------+---------------------------+---------------------------+---------------------------+---------------------------+---------------------------+
| 285856 | J7609 | 20150119 | 285856 | J7613 | 20150119 | 285856 | J0456 | 20150119 | 285856 | J0694 | 20150119 | 285856 | J1885 | 20150119 | 285856 | J2060 | 20150119 | 285856 | J2930 | 20150119 |
+---------------------------+---------------------------+---------------------------+---------------------------+---------------------------+---------------------------+---------------------------+
我正在寻找一种将不同数量的行转换为 sql server 2008 R2
中的列的方法。我在查询中创建了数据列 RANK
,因为最终我希望将透视列名称标记为 RANK
列中的值。然后,如果我能以某种方式 STUFF
将其他 3 个字段值一起合并到一个字段中,我将能够遍历后端语言中的行并适当地拆分字段结果。
这是当前的数据集:
我希望枢轴的最终结果产生这样的结果:
我还没有发现任何关于能够以这种 "dynamic" 方式旋转的信息。任何帮助将不胜感激。
正如我上面提到的,您需要区分每个 Rank
值。您已经说过这是一个计算值,您可以在每个值的末尾添加一个数字。添加该数字后,您仍然需要对其进行旋转。
首先看到这一点的最简单方法是先编写查询的硬编码版本。
示例数据:
create table yourdata
(
id int,
code varchar(50),
created datetime,
[rank] varchar(50)
);
insert into yourdata
select 285856, 'J7609', '2015-01-19', 'Principle' union all
select 285856, 'J7613', '2015-01-19', 'Other' union all
select 285856, 'J0456', '2015-01-19', 'Other' union all
select 285856, 'J0694', '2015-01-19', 'Other' union all
select 285856, 'J1885', '2015-01-19', 'Other' union all
select 285856, 'J2060', '2015-01-19', 'Other' union all
select 285856, 'J2930', '2015-01-19', 'Other';
静态查询:
select Principle_1, Other_1,
Other_2, Other_3, Other_4,
Other_5, Other_6
from
(
-- using row_number to get unique id for each rank
select
data = cast(id as varchar(10)) +' | '+ code +' | '+ convert(varchar(10), created, 112),
[rank] = [rank] + '_' +cast(row_number() over(partition by id, [rank]
order by id) as varchar(10))
from yourdata
) d
pivot
(
max(data)
for [rank] in (Principle_1, Other_1, Other_2, Other_3, Other_4,
Other_5, Other_6)
) p;
现在要执行此动态操作,您将使用列名创建一个 sql 字符串,然后执行该字符串:
DECLARE @cols AS NVARCHAR(MAX),
@query AS NVARCHAR(MAX)
select @cols = STUFF((SELECT ',' + QUOTENAME([rank] + '_' +cast(rn as varchar(10)))
from
(
select [rank],
rn = row_number() over(partition by id, [rank]
order by id)
from yourdata
) d
group by [rank], rn
order by rn, [rank] desc
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set @query = 'SELECT ' + @cols + '
from
(
select
data = cast(id as varchar(10)) +'' | ''+ code +'' | ''+ convert(varchar(10), created, 112),
[rank] = [rank] + ''_'' +cast(row_number() over(partition by id, [rank]
order by id) as varchar(10))
from yourdata
) x
pivot
(
max(data)
for [rank] in (' + @cols + ')
) p '
exec sp_executesql @query;
这会得到一个结果:
+---------------------------+---------------------------+---------------------------+---------------------------+---------------------------+---------------------------+---------------------------+
| Principle_1 | Other_1 | Other_2 | Other_3 | Other_4 | Other_5 | Other_6 |
+---------------------------+---------------------------+---------------------------+---------------------------+---------------------------+---------------------------+---------------------------+
| 285856 | J7609 | 20150119 | 285856 | J7613 | 20150119 | 285856 | J0456 | 20150119 | 285856 | J0694 | 20150119 | 285856 | J1885 | 20150119 | 285856 | J2060 | 20150119 | 285856 | J2930 | 20150119 |
+---------------------------+---------------------------+---------------------------+---------------------------+---------------------------+---------------------------+---------------------------+