简体   繁体   中英

T-SQL Dynamic Pivot on different and multiple columns

Table Student:

Studid      StuName     
=========================
1           'Marco Polo'
2           'Leroy Jenkins'

Table Subjects:

Subid      SubName     
===================
1           English
2           French
3           German
4           Math
5           Physics

Table Grades

Stuid      Subid          Grade1            Grade2
==================================================
1           1                10               6    
1           2                9                7    
2           1                8                4    
2           4                7                9    
2           5                6                10   

I would like to achieve 2 tables: Table1:

StuName      English 1      English 2      French 1       French 2
==================================================================
'Marco Polo'     10             6              9              7

Table1:

StuName      English 1      English 2      Math 1       Math 2      Physics 1       Physics 2
==================================================================
'Leroy Jenkins'    8             4              7              9    6              10

In your example the id on Student is StudId and in Grades it is StuId . This may or may not be a typo, but I left it as posted.

You need to unpivot the subject+gradenumber (I use the cross apply(values... ) method to unpivot in the code below but a union all or unpivot() version would work as well), and then pivot.

Since you only want to return columns specific to each student, you use a filter on the column list generation and in the inner query of the pivot and pass that parameter to sp_executesql for the execution of the generated code.

declare @cols nvarchar(max), @sql nvarchar(max), @StuId int;
set @StuId = 2;
set @cols = stuff((
    select ', ' + quotename(sub.subName+'1')+', '+ quotename(sub.subName+'2')
    from Grades g
      inner join Student stu
        on g.StuId = stu.StudId
      inner join Subjects sub 
        on g.SubId = sub.SubId
    where stu.StudId = @StuId
    order by 1
    for xml path (''), type).value('(./text())[1]','nvarchar(max)')
    ,1,2,'');
set @sql = '
    select StuName, '+ @cols +'
    from (
      select stu.StuName, u.SubName, u.Grade
      from Grades g
        inner join Student stu
          on g.StuId = stu.StudId
        inner join Subjects sub 
          on g.SubId = sub.SubId
        cross apply (values 
            (sub.SubName+''1'', g.Grade1)
          , (sub.SubName+''2'', g.Grade2)
          )u (SubName,Grade) 
      where stu.StudId = @StuId
      ) as t
    pivot (sum(Grade) for SubName in (' + @cols +')) p';

select CodeGenerated = @sql;
exec sp_executesql @sql ,N'@StuId int', @StuId;

rextester demo: http://rextester.com/DCLY81531

returns CodeGenerated :

select StuName, [English1], [English2], [Math1], [Math2], [Physics1], [Physics2]
    from (
      select stu.StuName, u.SubName, u.Grade
      from Grades g
        inner join Student stu
          on g.StuId = stu.StudId
        inner join Subjects sub 
          on g.SubId = sub.SubId
        cross apply (values 
            (sub.SubName+'1', g.Grade1)
          , (sub.SubName+'2', g.Grade2)
          )u (SubName,Grade) 
      where stu.StudId = @StuId
      ) as t
    pivot (sum(Grade) for SubName in ([English1], [English2], [Math1], [Math2], [Physics1], [Physics2])) p

for @StuId = 2 returns:

+---------------+----------+----------+-------+-------+----------+----------+
|    StuName    | English1 | English2 | Math1 | Math2 | Physics1 | Physics2 |
+---------------+----------+----------+-------+-------+----------+----------+
| Leroy Jenkins |        8 |        4 |     7 |     9 |        6 |       10 |
+---------------+----------+----------+-------+-------+----------+----------+

for @StuId = 1 returns:

+------------+----------+----------+---------+---------+
|  StuName   | English1 | English2 | French1 | French2 |
+------------+----------+----------+---------+---------+
| Marco Polo |       10 |        6 |       9 |       7 |
+------------+----------+----------+---------+---------+

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM