Sqlserver
 sql >> база данни >  >> RDS >> Sqlserver

Кръстосана заявка с динамични колони в SQL Server 2005 нагоре

Има два начина за извършване на PIVOT статичен, където твърдо кодирате стойностите и динамичен, където колоните се определят, когато изпълнявате.

Въпреки че ще искате динамична версия, понякога е по-лесно да започнете със статичен PIVOT и след това работете към динамичен.

Статична версия:

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

Вижте SQL Fiddle с демонстрация

Сега, ако не знаете стойностите, които ще бъдат трансформирани, можете да използвате Dynamic SQL за това:

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)

Вижте SQL Fiddle с демонстрация

И двете версии ще дадат едни и същи резултати.

Само за да завърша отговора, ако нямате PIVOT функция, тогава можете да получите този резултат с помощта на CASE и агрегатна функция:

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

Вижте SQL Fiddle с демонстрация



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. TSQL, за да получите подредени РАЗЛИЧНИ записи и след това да приложите номера на редове

  2. Как да актуализирате първичен ключ

  3. NEWID() срещу NEWSEQUENTIALID() в SQL Server:Каква е разликата?

  4. Параметър на стойността на таблицата със съхранени процедури на Dapper

  5. Как да изпълним асинхронно съхранена процедура на sql сървър и да гарантираме, че е завършена