不幸的是,mysql 不支持 windows 功能。使用 row_number() 或更好的累积总和(如 Oracle 支持)会更容易。
我将描述解决方案。假设您的表中有两个额外的列:
- ClassSeqNum - 一个从 1 开始并为每个课程日期递增 1 的序列。
- AbsentSeqNum - 每次学生缺课时从 1 开始的序列,然后在每次缺课时增加 1。
关键的观察是这两个值之间的差异对于连续缺席是恒定的。因为您使用的是 mysql,您可能会考虑将这些列添加到表中。在查询中添加它们是很大的挑战,这就是为什么这个答案这么长。
鉴于关键观察,您的问题的答案由以下查询提供:
select studentid, subjectid, absenceid, count(*) as cnt
from (select a.*, (ClassSeqNum - AbsentSeqNum) as absenceid
from Attendance a
) a
group by studentid, subjectid, absenceid
having count(*) > 2
(好的,这给出了每个科目的学生缺勤的每个顺序,但我认为您可以弄清楚如何将其缩减为学生列表。)
你如何分配序列号?在 mysql 中,您需要进行自连接。因此,以下添加了 ClassSeqNum:
select a.StudentId, a.SubjectId, count(*) as ClassSeqNum
from Attendance a join
Attendance a1
on a.studentid = a1.studentid and a.SubjectId = a1.Subjectid and
a.ClassDate >= s1.classDate
group by a.StudentId, a.SubjectId
以下添加缺席序列号:
select a.StudentId, a.SubjectId, count(*) as AbsenceSeqNum
from Attendance a join
Attendance a1
on a.studentid = a1.studentid and a.SubjectId = a1.Subjectid and
a.ClassDate >= a1.classDate
where AttendanceStatus = 0
group by a.StudentId, a.SubjectId
所以最终的查询看起来像:
with cs as (
select a.StudentId, a.SubjectId, count(*) as ClassSeqNum
from Attendance a join
Attendance a1
on a.studentid = a1.studentid and a.SubjectId = a1.Subjectid and
a.ClassDate >= s1.classDate
group by a.StudentId, a.SubjectId
),
a as (
select a.StudentId, a.SubjectId, count(*) as AbsenceSeqNum
from Attendance a join
Attendance a1
on a.studentid = a1.studentid and a.SubjectId = a1.Subjectid and
a.ClassDate >= s1.classDate
where AttendanceStatus = 0
group by a.StudentId, a.SubjectId
)
select studentid, subjectid, absenceid, count(*) as cnt
from (select cs.studentid, cs.subjectid,
(cs.ClassSeqNum - a.AbsentSeqNum) as absenceid
from cs join
a
on cs.studentid = a.studentid and cs.subjectid = as.subjectid
) a
group by studentid, subjectid, absenceid
having count(*) > 2