根据表列动态合并两列或更多列?

use*_*705 2 sql sql-server pivot

我有一个表,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
Run Code Online (Sandbox Code Playgroud)

员工表中存在很少的员工记录.我希望这是动态的.喜欢如果将来如果RelativesXYZsection 增加了一个名为add的子部分,那么我的查询应该返回Relatives_XYZ_Cost.

如何动态编写此查询?

Tar*_*ryn 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;
Run Code Online (Sandbox Code Playgroud)

请参阅SQL Fiddle with Demo.

如果您需要查询灵活,那么您将转换为使用动态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)
Run Code Online (Sandbox Code Playgroud)

请参阅SQL Fiddle with Demo

两者的结果是:

| 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 |
Run Code Online (Sandbox Code Playgroud)