2014-05-17 24 views
0

我有以下幾列的出勤表:填補了樞軸結果SQL Server的虛擬列

StudentID, Date, Attendance 

現在我運行一個查詢來獲取的考勤結果

DECLARE @paramList VARCHAR(MAX) 


SET @paramList = STUFF((SELECT DISTINCT ',[' + 
CONVERT(varchar(10), [Date], 20) + ']' 
FROM AttendenceT 
WHERE Date > '2014-01-01' AND Date < '2014-01-31' 
FOR XML PATH('')) ,1,1,'') 

DECLARE @query NVARCHAR(MAX) 

SET @query = 'SELECT StudentID, ' + @paramList 
+ ' FROM(SELECT * FROM AttendenceT)src 
PIVOT(SUM(Attendence) FOR Date IN (' + @paramList + ')) pvt' 

EXEC sp_executesql @query 

的結果

enter image description here

結果是,除了失蹤當天OK在考勤表中,結果中沒有列。我想要修改查詢,以便即使日期不在考勤表中,它的列仍然可用。

請注意,我不是SQL的專家。我創建了這個查詢使用谷歌和主要stackoverflow過去的問題的答案。

回答

1

首先得到一個日曆表。這是一個涉及這個主題的SO post。這個表是永久性部分還是數據庫,臨時表還是表變量都無關緊要。我們稱這個表爲Calendar,其中一列爲TheDate

下一個加入Calendar到所有學生的名單。我將使用你的AttendenceT表,因爲這是你在問題中提到的唯一一個。如果你有一個真實的Student表,那會更好,因爲最終的結果將會列出那些從未參加過的學生(我認爲這將是有用的信息)。

select 
    s.StudentID 
    ,c.TheDate 
from Calendar as c 
cross apply (
     select distinct StudentID from AttendenceT -- Put the Student table here if you have one 
     ) as s; 

最有可能你只是想,如果needbe一定的數據範圍,從而增加WHERE條款。

然後你就可以加入給你的考勤表:

select 
    s.StudentID 
    ,c.TheDate 
    ,ISNULL(a.Attendance, 0) 
from Calendar as c 
cross apply (
     select distinct StudentID from AttendenceT 
     ) as s 
left outer join AttendenceT as a 
    on a.StudentID = s.StudentID 
    and a.Date = c.TheDate 
-- optional for a limited date range. 
where c.TheDate between <your star date> and <your end date>; 

這會給你日起每學生在你的範圍內,再加上它存在勤。 ISNULL()負責處理不存在的示例。

商店從該查詢輸出到一個臨時表:

select 
    ... 
into #TempAttendence 
from ... etc. 

在您發佈的查詢來替換所有AttendenceT與引用和#TempAttendence你會得到你所需的輸出。

+0

謝謝Michael Green。這已經解決了除NULL問題以外的問題。當我使用ISNULL(a.Attendance,0)時,出現以下錯誤消息 對象或列名稱缺失或爲空。對於SELECT INTO語句,請確認每列都有一個名稱。對於其他語句,查找空的別名。別名定義爲「」或[]是不允許的。將別名更改爲有效的名稱。 –

+1

通過將值更新爲 得到修正的錯誤ISNULL(a.Attendence,0)AS Attendence –