我正在构建一个管理学生和类(class)的系统。学生可以更换类(class),但在同一天不能被分配到多个类(class)。我正在重新考虑我的实现方式。
显而易见的方法是拥有 attendance_periods
表,其中包含列 student_id
, class_id
, from
和to
。但是,这可能会存储无效数据。例如,学生 A 在 2021-08-01 至 2021-09-01 期间在 A 类,在 2021-08-15 至 2021-09-15 期间在 B 类。至少,据我所知,在数据库层面没有办法杜绝此类情况的发生。
为了防止这种重叠发生,我让表格只有 student_id
, class_id
和from
,与 student_id
对和from
独特且class_id
可以为空。该行不是“说”学生从日期 A 到日期 B 在 X 类,而是仅说明学生加入类(class)或离开学校的时间(如果他们未分配到任何类(class))。
但是,这使得一些查询变得非常困难。例如,要获取特定日期哪个类(class)的学生,这是我一直在使用的查询:
select
`class_attendance_periods`.*
from
`class_attendance_periods`
left join (
select
`id` as `later_id`,
`student_id` as `later_student_id`,
`class_id` as `later_class_id`,
`from` as `later_from`
from
`class_attendance_periods`
where
`from` <= '2021-08-30'
) as `later` on `class_attendance_periods`.`student_id` = `later`.`later_student_id`
and `class_attendance_periods`.`from` < `later`.`later_from`
where
`later`.`later_from` is null
and `class_attendance_periods`.`from` <= '2021-08-30'
但是,我现在要做的工作,需要把每个类(class)的学生都取一段时间。这当然是我可以在服务器的 PHP 端工作的东西,但我不知道如何将查询限制为适用的行。例如,WHERE from <= last_day_of_the_interval
条件阻止获取我不需要的 future 出勤期,但我不知道如何不获取过去不需要的行。另外,如果可能的话,我希望数据库能够承担繁重的工作。
所以我的问题是双重的:
1- 有没有更好的方法来实现这种情况?我感兴趣的是让数据库不允许无效数据,同时可以轻松查询给定日期的类(class)学生或给定时间段的所有类(class)学生。
2-如果这个结构还不错,有没有办法让查询动态计算出勤期的结束时间(即“截止”日期)?比如添加 next attendance period's 'from' minus one day
柱子。这样查询会更容易进行。
最佳答案
However, this has been making some queries very difficult. For example, to get what students are on which class on a given day
WITH
cte AS (
SELECT *, ROW_NUMBER() OVER (PARTITION BY student_id ORDER BY `from` DESC) rn
FROM class_attendance_periods
WHERE `from` <= '2021-08-30'
)
SELECT *
FROM cte
WHERE rn = 1;
需要 MySQL 版本 8+。
关于mysql - 在(Mysql?)中存储不重叠日期范围的最佳方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68984779/