Sqlserver
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Sqlserver

Truy vấn bảng chéo với cột động trong SQL Server 2005 trở lên

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)

Xem SQL Fiddle với Demo

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

Xem SQL Fiddle with Demo



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Nhận một giá trị ngẫu nhiên từ một phạm vi trong MS SQL?

  2. Tìm hiểu Luôn luôn BẬT Nhóm sẵn có giữa các Phiên bản Máy chủ SQL dựa trên Linux. Phần 1

  3. Cách giải quyết lỗi độ dài tối đa (quá dài) trong truy vấn sql c #

  4. Hàm trong SQL Server 2008 tương tự như hàm GREATEST trong mysql?

  5. Tại sao UDF lại chậm hơn nhiều so với truy vấn con?