更好地检测许多不同唯一用户ID的连续记录数

时间:2013-08-16 17:16:00

标签: sql sql-server cursor

所以我正在等待我的查询运行(大约需要5分钟)

我开发了一个查询,该查询将查看学生的出勤记录,确定一组出勤代码并根据日期和课程时间对其进行分组。

如果我试图为特定学生找到最多的缺席数量,但是当我尝试创建一个表格显示所有活跃学生缺勤次数最多的表格时,此查询效果很好。

为了实现这一点,我使用游标将StudentNo(唯一ID)分配给参数,然后运行我的原始查询,并将结果放入名为@results的临时表中。

这是我的代码:

DECLARE @StudentId INT
DECLARE @getStudentId CURSOR
DECLARE @Results TABLE(StudentNo INT,AttendanceCode VarChar(2),StartDate       DateTime,EndDate DateTime,"# of Classes" INT)
SET @getStudentId = CURSOR FOR
SELECT StudentNo
FROM [dbo].[Students]
OPEN @getStudentId
FETCH NEXT
FROM @getStudentId INTO @StudentId
WHILE @@FETCH_STATUS = 0
BEGIN

WITH AttendanceCodeMaster AS
(SELECT 
    [dbo].[Students].StudentNo,
    CAST(CONVERT(date,[dbo].[CourseOfferingSchedule].ClassDate,101) as DATETIME) + CAST(CONVERT(time,dbo.CourseOfferingSchedule.ClassStartTime,101) AS DATETIME) as ClassDate,
    [dbo].[CourseOfferingAttendanceScheduled].AttendanceCode

FROM [dbo].[CourseOfferingAttendanceScheduled]
    INNER JOIN [dbo].[Students] on [dbo].[CourseOfferingAttendanceScheduled].StudentNo = [dbo].[Students].StudentNo 
    INNER JOIN dbo.[CourseOfferingSchedule] on [dbo].[CourseOfferingAttendanceScheduled].ScheduleID =  [dbo].[CourseOfferingSchedule].ScheduleID
    INNER JOIN [dbo].[StudentStatus] on  [dbo].[Students].StudentStatusID =  [dbo].[StudentStatus].StudentStatusID

where 

[dbo].[Students].StudentNo = @StudentId and StudentStatus = 'Active' and Complete = 'Y' 

),

RunGroup AS
(SELECT StudentNo,ClassDate, AttendanceCode, (SELECT COUNT(*) From AttendanceCodeMaster as G WHERE G.AttendanceCode <> GR.AttendanceCode AND G.ClassDate <= GR.ClassDate) as RunGroup
FROM AttendanceCodeMaster as GR ),

AbsenceStreaks AS
(SELECT 
StudentNo,
AttendanceCode, 
MIN(ClassDate) as StartDate, 
MAX(ClassDate)as EndDate,
COUNT(*) as '# of Classes' 
FROM RunGroup
where AttendanceCode = 'A'
GROUP BY StudentNo,AttendanceCode, RunGroup),

LongestStreak AS
(SELECT TOP 1 * FROM AbsenceStreaks
Order BY '# of Classes' Desc)

INSERT INTO @Results SELECT * FROM LongestStreak

FETCH NEXT
FROM @getStudentId INTO @StudentId

END
CLOSE @getStudentId
DEALLOCATE @getStudentId

SELECT * from @Results
where "# of Classes" >= 30

order by StudentNo

1 个答案:

答案 0 :(得分:0)

您不需要游标来解决此问题。以下内容可能会对字段内容和名称做出一些假设(因为很难遵循您的查询逻辑),但它应该为您提供正确的方法。

关键是通过枚举学生(在课堂上)的所有课日,然后根据他们是否参加,列举学生的所有课时,可以识别一串缺席。对于一系列缺席或存在,这些值之间的差异是不变的。

select studentNo, grp, AttendanceCode, count(*) as numInRow,
       min(ClassDate) as DateStart, max(ClassDate) as DateEnd
from (select acm.*
             (row_number() over (partition by StudentNo order by ClassDate) -
              row_number() over (partition by StudentNo, AttendanceCode order by ClassDate) 
             ) as grp
      from AttendanceCodeMaster acm
     ) acm
group by studentNo, grp, AttendanceCode;

(我不确定某处是否还有类代码。)

这应该为您提供想要查找缺席或在场人员序列的信息。

StudentNo,ClassDate,AttendanceCode,(来自AttendanceCodeMaster的SELECT COUNT(*)作为G WHERE G.AttendanceCode&lt;&gt; GR.AttendanceCode和G.ClassDate&lt; = GR.ClassDate)作为RunGroup 来自AttendanceCodeMaster