我会有这样的事情:
Subjects( SubjectId PK, Name, etc... )
Classes( ClassId PK, SubjectId, DateTime periodBegin, etc... )
Students( StudentId PK, Name, etc... )
StudentAttendance( StudentId PK, ClassId PK )
Subjects
包含每个科目Classes
的记录,包含学校日历中每个预定课程的记录。该Classes
表将需要填充实际的班级集会 - 您可以在它们发生时添加它们,或者在学年开始时批量添加它们。该Students
表是不言自明的,该StudentAttendance
表列出了哪些学生积极参加了特定课程。
不要认为像这样的表StudentAttendance
是一个糟糕的设计——这是一个多对多连接表的典型示例。一些数据库在连接表中有数十亿行并不罕见,但因为它只包含两个键值(可能是 int32 或 int64),所以它不会占用太多磁盘空间。
这是一个查询,用于查找哪些学生没有参加特定课程:
SELECT
Name
FROM
Students
WHERE
StudentId NOT IN (
SELECT
StudentId
FROM
StudentAttendance
INNER JOIN Classes ON StudentAttendance.ClassId = Classes.ClassId
WHERE
StudentAttendance.ClassId = @classId
)
这是一个查询,用于获取每个参加特定科目的学生的出勤人数。除以 ( SELECT Count(*) FROM Clases WHERE Classes.SubjectId = @subject
) 得到每个学生的出勤率。如果学生从未参加过任何课程(故意或因为他们没有注册),那么他们将不会出现在列表中。
SELECT
Students.Name
COUNT(*) As AttendanceCount
FROM
StudentAttendance
INNER JOIN Classes ON Classes.ClassId = StudentAttendance.ClassId
INNER JOIN Students ON Students.StudentId = StudentAttendance.StudentId
GROUP BY
StudentId
WHERE
Classes.SubjectId = @subjectId