我有一个名为SectionNames
的表,如下所示
SectionID SectionCode Subsection 1 xYz Individual 2 xYz Family 3 CYD Friends 4 PCPO level1 5 PCPO level2 6 PCPO level3
等等。因此,将来我们可以为每个部分代码添加一个或多个子部分。
还有一个表,它是上述SectionNames
表和Employee
表的参考表,包含员工数据。
ID EmployeeID SectionID Cost 1 1 1 $200 2 1 2 $300 3 1 3 $40 4 1 4 $10 5 1 5 No Level 6 1 6 No Level 7 1 7 $20 8 1 8 No Level 9 1 9 No Level
所以我希望这些表中的输出看起来像:
EmployeeID Individual_xyz_Cost Family_xyz_Cost Friends_xyz_cost level1_PCPO_cost level2_PCPO_Cost
1 $200 $300 $400 $10 NoLevel
我的员工表中存在很少的员工记录。我希望这是动态的。如果将来如果为Relatives
部分添加了一个名为XYZ
的子部分,则我的查询应返回Relatives_XYZ_Cost
。
如何动态编写此查询?
答案 0 :(得分:6)
您需要使用PIVOT
函数将数据从列转换为行。如果您将需要未知数量的值作为列,那么您将需要使用动态SQL。
首先看到静态或硬编码版本然后将其转换为动态SQL版本会更容易。如果您具有已知数量的值,则使用静态版本:
select *
from
(
select e.employeeid,
s.subsection +'_'+s.sectioncode+'_Cost' Section,
e.cost
from employee e
inner join sectionnames s
on e.sectionid = s.sectionid
) src
pivot
(
max(cost)
for section in (Individual_xYz_Cost, Family_xYz_Cost,
Friends_CYD_Cost, level1_PCPO_Cost,
level2_PCPO_Cost, level3_PCPO_Cost)
) piv;
如果您需要灵活的查询,那么您将转换为使用动态SQL:
DECLARE @cols AS NVARCHAR(MAX),
@query AS NVARCHAR(MAX)
select @cols = STUFF((SELECT ',' + QUOTENAME(subsection +'_'+sectioncode+'_Cost')
from SectionNames
group by subsection, sectioncode, sectionid
order by sectionid
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set @query = 'SELECT employeeid,' + @cols + '
from
(
select e.employeeid,
s.subsection +''_''+s.sectioncode+''_Cost'' Section,
e.cost
from employee e
inner join sectionnames s
on e.sectionid = s.sectionid
) x
pivot
(
max(cost)
for section in (' + @cols + ')
) p '
execute(@query)
两者的结果是:
| EMPLOYEEID | INDIVIDUAL_XYZ_COST | FAMILY_XYZ_COST | FRIENDS_CYD_COST | LEVEL1_PCPO_COST | LEVEL2_PCPO_COST | LEVEL3_PCPO_COST |
----------------------------------------------------------------------------------------------------------------------------------
| 1 | $200 | $300 | $40 | $10 | No Level | No Level |