我有3个表Table 2我们有columnName字段他们可以动态增长当时我们只有5列每个CTypeId他们可以是6或10等Table3我们有列值.
例如,AccountManagerFrom Table 2在Table 3 Jack / Kate
类似的其他列中具有值,它们的值是
ColumnName | Values
Channel | PS
StartDate | 06/03/2017
Run Code Online (Sandbox Code Playgroud)
我想结果像这样
我尝试使用Pivot函数与以下查询:
Declare @Columns nvarchar(max)
Declare @a nvarchar(max)
Set @Columns = (select STUFF((select ',' + '[' + Convert(varchar(200), ColumnName) + ']' from CharityTypeInformationDynamicFields FOR XML PATH('')), 1,1, ''))
Declare @sql nvarchar(max)
= 'Select *
from
(select cd.Id, cd.Value, ci.ColumnName
from Table3 cd
Inner Join Table2 ci
on ci.Id = cd.DynamicFieldID
) as s
Pivot(MAX(Value) ForColumnName IN ('+@columns+')) as pvt'
Select @sql
Run Code Online (Sandbox Code Playgroud)
但查询给出了结果:
我需要更改什么来实现我想要的输出?
您需要解决一些问题才能获得所需的结果.但在尝试查询的动态sql版本之前,我总是建议您先尝试编写硬编码或静态版本来获取最终结果.这允许您获得没有错误的所需结果,然后将其转换为动态sql作为您的最终查询.
首先,让我们将您的表结构和示例数据放入可重用的脚本中.您似乎只需要table2并table3获得最终结果:
create table #table2
(
id int,
ctypeid int,
columnname varchar(50)
)
insert into #table2
values
(1, 20, 'Account Manager'), (2, 20, 'Channel'),
(3, 20, 'Start Date'), (4, 20, 'End Date'),
(5, 20, 'Gross Annual'), (6, 6, 'Account Manager'),
(7, 6, 'Channel'), (8, 6, 'Start Date'),
(9, 6, 'End Date'), (10, 6, 'Gross Annual');
create table #table3
(
id int,
table2id int,
value varchar(50)
)
insert into #table3
values
(1, 1, 'Jack / Kate'), (2, 2, 'PS'), (3, 3, '06/03/2017'),
(4, 4, '07/03/2017'), (5, 5, '2500'), (6, 6, 'Ollie'),
(7, 7, 'D2D'), (8, 8, '06/03/2017'), (9, 9, '06/03/2017'),
(10, 10, '5232'), (11, 1, 'Jack'), (12, 2, 'PSP'),
(13, 3, '06/03/2017'), (14, 4, '07/03/2017'), (15, 5, '7000'),
(16, 1, 'Jack Sparrow'), (17, 2, 'PS Sparrow'), (1, 3, '06/03/2017'),
(19, 4, '07/03/2017'), (20, 5, '3000'), (21, 6, 'John'),
(22, 7, 'JEDF'), (23, 8, '06/03/2017'), (24, 9, '06/03/2017'),
(25, 10, '5232');
Run Code Online (Sandbox Code Playgroud)
接下来,您需要编写PIVOT查询.你最终的结果只包括3列中的值CTypeId,Value以及ColumnName,让您的查询PIVOT的开始将是:
select
CTypeId,
[Account Manager], [Channel], [Start Date],
[End Date], [Gross Annual]
from
(
select ci.CTypeId, cd.Value, ci.ColumnName
from #Table3 cd
Inner Join #Table2 ci
on ci.Id = cd.Table2Id
) d
pivot
(
max(Value)
for ColumnName in ([Account Manager], [Channel], [Start Date],
[End Date], [Gross Annual])
) piv
Run Code Online (Sandbox Code Playgroud)
演示.但是,由于您在Value列中聚合字符串值,因此每个字段只会返回一行CTypeId:
+---------+-----------------+---------+------------+------------+---------------+
| CTypeId | Account Manager | Channel | Start Date | End Date | Gross Annual |
+---------+-----------------+---------+------------+------------+---------------+
| 6 | Ollie | JEDF | 06/03/2017 | 06/03/2017 | 5232 |
| 20 | Jack Sparrow | PSP | 06/03/2017 | 07/03/2017 | 7000 |
+---------+-----------------+---------+------------+------------+---------------+
Run Code Online (Sandbox Code Playgroud)
这不是你想要的,所以你需要做一些事情来允许多行.如果查看子查询返回的数据示例:
+---------+-------------+------------------+
| CTypeId | Value | ColumnName |
+---------+-------------+------------------+
| 20 | Jack / Kate | Account Manager |
| 20 | PS | Channel |
| 20 | 06/03/2017 | Start Date |
| 20 | 07/03/2017 | End Date |
| 20 | 2500 | Gross Annual |
| 6 | Ollie | Account Manager |
| 6 | D2D | Channel |
| 6 | 06/03/2017 | Start Date |
| 6 | 06/03/2017 | End Date |
| 6 | 5232 | Gross Annual |
+---------+-------------+------------------+
Run Code Online (Sandbox Code Playgroud)
您将看到在组合CTypeId和ColumnName值上有唯一的数据,因此您可以使用row_number子查询中的窗口函数创建唯一的行号,该窗口函数可用于对数据透视的数据进行唯一分组.通过将以上PIVOT代码更改为:
select
CTypeId,
[Account Manager], [Channel], [Start Date],
[End Date], [Gross Annual]
from
(
select ci.CTypeId, cd.Value, ci.ColumnName,
rn = row_number() over(partition by ci.CTypeId, ci.ColumnName order by cd.Value)
from #Table3 cd
Inner Join #Table2 ci
on ci.Id = cd.Table2Id
) d
pivot
(
max(Value)
for ColumnName in ([Account Manager], [Channel], [Start Date],
[End Date], [Gross Annual])
) piv
order by CTypeId
Run Code Online (Sandbox Code Playgroud)
看看demo,你会得到想要的结果:
+---------+-----------------+------------+------------+------------+---------------+
| CTypeId | Account Manager | Channel | Start Date | End Date | Gross Annual |
+---------+-----------------+------------+------------+------------+---------------+
| 6 | John | D2D | 06/03/2017 | 06/03/2017 | 5232 |
| 6 | Ollie | JEDF | 06/03/2017 | 06/03/2017 | 5232 |
| 20 | Jack | PS | 06/03/2017 | 07/03/2017 | 2500 |
| 20 | Jack / Kate | PS Sparrow | 06/03/2017 | 07/03/2017 | 3000 |
| 20 | Jack Sparrow | PSP | 06/03/2017 | 07/03/2017 | 7000 |
+---------+-----------------+------------+------------+------------+---------------+
Run Code Online (Sandbox Code Playgroud)
一旦获得了所需的最终结果,就可以轻松地将查询转换为动态SQL:
Declare @Columns nvarchar(max)
Declare @a nvarchar(max)
Set @Columns = stuff((select distinct ',' + quotename(ColumnName)
from #table2
for xml path(''), type).value('.', 'nvarchar(max)'), 1, 1, '');
Declare @sql nvarchar(max)
= 'Select CTypeId, '+@Columns+'
from
(
select ci.CTypeId, cd.Value, ci.ColumnName,
rn = row_number() over(partition by ci.CTypeId, ci.ColumnName order by cd.Value)
from #Table3 cd
Inner Join #Table2 ci
on ci.Id = cd.Table2Id
) as s
Pivot(MAX(Value) For ColumnName IN ('+@columns+')) as pvt
order by CTypeId'
execute(@sql);
Run Code Online (Sandbox Code Playgroud)
见演示.这与硬编码版本具有相同的结果,具有动态sql的灵活性.