我在Table 2
中有3个表我们有columnName
字段他们可以增长的字段当时我们只有5列每个CTypeId
他们可以是6或10等。在Table3
中,我们有列值。
例如AccountManager
Table 2
来自Table 3
Jack / Kate
类似地,其他列及其值是
ColumnName | Values
Channel | PS
StartDate | 06/03/2017
我想要像这样的结果
我尝试使用Pivot Function并使用以下查询:
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
但是查询给出了结果:
我需要更改什么来实现我想要的输出?
答案 0 :(得分:9)
为了获得您想要的结果,您需要解决一些问题。但在尝试查询的动态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');
接下来,您需要编写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
Demo。但是,由于您要在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 |
+---------+-----------------+---------+------------+------------+---------------+
这不是你想要的,所以你需要做一些事情以允许多行。如果查看子查询返回的数据样本:
+---------+-------------+------------------+
| 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 |
+---------+-------------+------------------+
您会发现自己拥有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
See 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 |
+---------+-----------------+------------+------------+------------+---------------+
获得所需的最终结果后,将查询转换为动态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);
See Demo。这与硬编码版本具有相同的结果,具有动态sql的灵活性。