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

Sql 检测许多不同唯一用户ID的连续记录数的更好方法,sql,sql-server,cursor,Sql,Sql Server,Cursor,所以我现在正在等待我的查询运行,大约需要5分钟 我开发了一个查询,可以查看学生的出勤记录,识别出勤代码,并根据日期和上课时间对其进行分组 如果我试图查找某个学生的最高缺勤次数,那么这个查询非常有效,但是当我试图创建一个表来显示所有活跃学生的最高缺勤次数时,这个查询会变得更加棘手 为了实现这一点,我使用光标将StudentNo唯一id分配给一个参数,然后运行我的原始查询,并将结果放入一个名为@results的临时表中 这是我的密码: DECLARE @StudentId INT DECLARE @

所以我现在正在等待我的查询运行,大约需要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

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

关键是,可以通过列举一个班级中某个学生的所有上课天数,然后根据是否参加来列举该学生的所有上课天数来识别一系列缺课。对于一系列的缺席或在场,这些值之间的差异是恒定的

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;
我不确定那里是否也有类代码

这将为您提供想要查找缺席或在场序列的信息

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中选择COUNT*作为G,其中G.AttendanceCode GR.AttendanceCode和G.ClassDate您到底有什么问题?提示1:使用别名和缩进使您的代码更易于阅读。哇,这比我以前的方式快多了,谢谢!上周我还在度假,否则我早就感谢你了!