2

3 つのテーブルのデータに基づいて、動的列を含むクエリを作成しようとしています。

これはデータベース構造です:

学生

  • studentID int
  • studentNumber int
  • studentName nvarchar(100).

テスト:

  • examID int
  • examName varchar(100)
  • examenDate datetime

試験登録:

  • studentID int
  • examID int

EXAM_REGISTRATION学生が試験に登録すると、テーブルにレコードが追加されます。

私が取得しようとしているのは、次のように、ピボット テーブル内のすべての試験とすべての学生のリストで、どの学生がどの試験に登録したかを確認することです。

ここに画像の説明を入力

率直に言って、どこから始めればよいかわかりません。

すべてを個別にクエリしてまとめることはできますが、それらを 1 つのクエリに結合するにはどうすればよいでしょうか?

私はピボットテーブルを研究してきましたが、すべての例は1つのテーブルからのみクエリを実行しているようMINで、AVGなどの数値と関数を使用しています.

誰かが私を助けてくれますか?

4

2 に答える 2

1

OK、行こう

遊ぶためのいくつかのデータ

create table #student
(studentID int, studentNumber int, studentName nvarchar(100))
create table #exam 
(examID int, examName nvarchar(100), examDate datetime)
create table #examReg
(studentID int, examID int)

insert into #student
values (1, 787878, 'pierwszy')
,(2, 89898, 'drugi')
,(3, 343434, 'trzeci')
,(4, 121212, 'czwarty')

insert into #exam
values (1, 'exPierwszy', GETDATE())
,(2, 'exDrugi', GETDATE())
,(3, 'exTrzeci', GETDATE())

insert into #examReg
values (1,2),(1,3)
, (2,2),(2,3)
,(3,1),(3,2)
,(4,1),(4,2),(4,3)

そして今、主要部分、そして説明

まず、ピボットクエリを取得する必要があります

select examName, examDate , min([1])  , min([2]), min([3]) ,min([4])--studentID as studentID, examDate --,studentNumber
from 
(select a.studentID , studentNumber, examDate, examName
from #student a 
join #examReg b on a.studentID = b.studentID
join #exam c on c.examID = b.examID ) as m
pivot
(min(studentNumber) FOR studentID in ([1],[2],[3],[4])) as t
group by examName, examDate

ピボット宣言でselectステートメントとstudentIDリストを変更するだけで、これらの部分を動的に生成する必要があるため、以前に記述したクエリをコピーして、列をトークンに置き換えます。

    declare @sqlTemplate nvarchar(max) = 
    'select examName, examDate @@sqlColumnList@@
    from 
    (select a.studentID , studentNumber, examDate, examName
    from #student a 
    join #examReg b on a.studentID = b.studentID
    join #exam c on c.examID = b.examID ) as m
    pivot
    (min(studentNumber) FOR studentID in (@@sqlStudentIDList@@)) as t
    group by examName, examDate
'

その後、tsqlで文字列を連結して列リストとstudentIDリストを生成します

declare @sqlColumnList nvarchar(max) = ''
select @sqlColumnList += ',min([' + cast(studentID as nvarchar(10)) + ']) as [' + studentName +'(' + cast(studentNumber as nvarchar(10)) + ')]'
from #student
declare @sqlStudentIDList nvarchar(max) = ''
select @sqlStudentIDList += '[' + CAST(studentID as nvarchar(10)) + '],'
from #student

set @sqlStudentIDList = SUBSTRING(@sqlStudentIDList, 0, LEN(@sqlStudentIDList))
select @sqlStudentIDList

一度入手したら、前のテンプレートのトークンを置き換えるだけです。

set @sqlTemplate = REPLACE(@sqlTemplate, '@@sqlColumnList@@', @sqlColumnList)
set @sqlTemplate = REPLACE(@sqlTemplate, '@@sqlStudentIDList@@', @sqlStudentIDList)


select @sqlTemplate

exec sp_executesql @sqlTemplate

このリンクの動的goについて読みたい場合は、msdnのピボットgoについて詳しく読みたい場合はこれで終わりです。

編集:コメントからの質問のクエリを調整するには、@sqlColumnListをそのように変更する必要があります

select @sqlColumnList += ',min(' + QUOTENAME(studentID)  + ') as Student' + CAST(studentID as nvarchar(10))  + '_REG,
'''+ studentName + ''' as Student' + cast(studentID as nvarchar(10)) + '_NAME,
'+ cast(studentID as nvarchar(10)) + ' as Student' + cast(studentID as nvarchar(10)) + '_ID'
from #student
于 2013-01-17T13:06:15.373 に答える
0

これはデータのピボットです。私はこれを他の答えとは少し異なる方法で実行します。すべての値がわかっている場合は、値をハードコーディングできます。

静的バージョンは次のようになります。

select examname,
  examendate,
  IsNull([Smith, John (14323)], 'false') [Smith, John (14323)],
  IsNull([Craft, Peter (14334)], 'false') [Craft, Peter (14334)],
  IsNull([Davis, Alan (13432)], 'false') [Davis, Alan (13432)],
  IsNull([Newman, Ted (133123)], 'false') [Newman, Ted (133123)]
from
(
  select e.examname,
    e.examenDate,
    s.studentName + ' ('+cast(s.studentnumber as varchar(50))+')' studentNameNum,
    'true ' as Flag
  from exam e
  left join exam_registration er
    on e.examid = er.examid
  right join student s
    on er.studentid = s.studentid
) src
pivot
(
  max(flag)
  for studentNameNum in ([Smith, John (14323)], [Craft, Peter (14334)],
                      [Davis, Alan (13432)], [Newman, Ted (133123)])
) piv

デモで SQL Fiddle を参照してください

値が不明な場合、クエリは次のようになります。

DECLARE @cols AS NVARCHAR(MAX),
    @colsNull AS NVARCHAR(MAX),
    @query  AS NVARCHAR(MAX)

select @cols = STUFF((SELECT distinct ',' + QUOTENAME(s.studentName + ' ('+cast(s.studentnumber as varchar(50))+')') 
                    from student s
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

select @colsNull = STUFF((SELECT distinct ',IsNull(' + QUOTENAME(s.studentName + ' ('+cast(s.studentnumber as varchar(50))+')')+', ''false'')'+' as '+QUOTENAME(s.studentName+' ('+cast(s.studentnumber as varchar(50))+')') 
                    from student s
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

set @query = 'SELECT examname,
                  examenDate,' + @colsNull + ' from 
             (
                select e.examname,
                  e.examenDate,
                  s.studentName + '' (''+cast(s.studentnumber as varchar(50))+'')'' studentNameNum,
                  ''true '' as Flag
                from exam e
                left join exam_registration er
                  on e.examid = er.examid
                right join student s
                  on er.studentid = s.studentid
            ) x
            pivot 
            (
                max(flag)
                for studentNameNum in (' + @cols + ')
            ) p '

execute(@query)

デモで SQL Fiddle を参照してください

結果は次のようになります。

| EXAMNAME |          EXAMENDATE | CRAFT, PETER (14334) | DAVIS, ALAN (13432) | NEWMAN, TED (133123) | SMITH, JOHN (14323) |
----------------------------------------------------------------------------------------------------------------------------
|   Exam 1 | 2013-01-01 12:00:00 |                false |               false |                true  |               false |
|   Exam 2 | 2013-01-01 14:00:00 |                true  |               false |                false |               true  |
|   Exam 3 | 2013-01-02 12:00:00 |                true  |               true  |                false |               false |
|   Exam 4 | 2013-01-02 14:00:00 |                false |               false |                true  |               false |
|   Exam 5 | 2013-01-03 12:00:00 |                false |               false |                false |               true  |
于 2013-01-17T15:23:53.273 に答える