Có hai cách để thực hiện PIVOT
static nơi bạn mã hóa cố định các giá trị và động nơi các cột được xác định khi bạn thực thi.
Mặc dù bạn sẽ muốn có phiên bản động, nhưng đôi khi bắt đầu bằng PIVOT
tĩnh sẽ dễ dàng hơn và sau đó làm việc theo hướng năng động.
Phiên bản tĩnh:
SELECT studentid, name, sex,[C], [C++], [English], [Database], [Math], total, average
from
(
select s1.studentid, name, sex, subjectname, score, total, average
from Score s1
inner join
(
select studentid, sum(score) total, avg(score) average
from score
group by studentid
) s2
on s1.studentid = s2.studentid
) x
pivot
(
min(score)
for subjectname in ([C], [C++], [English], [Database], [Math])
) p
Xem SQL Fiddle với bản trình diễn
Bây giờ, nếu bạn không biết các giá trị sẽ được chuyển đổi thì bạn có thể sử dụng Dynamic SQL cho việc này:
DECLARE @cols AS NVARCHAR(MAX),
@query AS NVARCHAR(MAX)
select @cols = STUFF((SELECT distinct ',' + QUOTENAME(SubjectName)
from Score
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set @query = 'SELECT studentid, name, sex,' + @cols + ', total, average
from
(
select s1.studentid, name, sex, subjectname, score, total, average
from Score s1
inner join
(
select studentid, sum(score) total, avg(score) average
from score
group by studentid
) s2
on s1.studentid = s2.studentid
) x
pivot
(
min(score)
for subjectname in (' + @cols + ')
) p '
execute(@query)
Cả hai phiên bản sẽ mang lại kết quả giống nhau.
Chỉ để làm tròn câu trả lời, nếu bạn không có PIVOT
thì bạn có thể nhận được kết quả này bằng cách sử dụng CASE
và một hàm tổng hợp:
select s1.studentid, name, sex,
min(case when subjectname = 'C' then score end) C,
min(case when subjectname = 'C++' then score end) [C++],
min(case when subjectname = 'English' then score end) English,
min(case when subjectname = 'Database' then score end) [Database],
min(case when subjectname = 'Math' then score end) Math,
total, average
from Score s1
inner join
(
select studentid, sum(score) total, avg(score) average
from score
group by studentid
) s2
on s1.studentid = s2.studentid
group by s1.studentid, name, sex, total, average