2014-05-17 22 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 –