我正在为课程编写内部注册表单。我正在研究一个简单的函数,它将检查用户是否选择了具有冲突时间表的类(例如,下午1-2点开课,以及同一天下午1-3点开课)。
假设我正在使用mysqli
并获取用户从具有开始和结束datetime
字段的MySQL表中选择的类,那么比较最有效和/或最有效的方法是什么?多个类,以查看它们是否冲突?
编辑:这是一个示例表:
====================================================
| id | start | end |
====================================================
| 1 | 2012-10-01 08:00:00 | 2012-10-01 08:00:00 |
====================================================
显然,表格中会有其他数据(如标题,描述等),但我想我可能只需要上面的数据进行比较。我将有一个数组,其中包含用户注册的每个类的id
。
对不起,如果这是重复的,我确实进行了搜索,之前没有看到这个问题。
答案 0 :(得分:0)
我不确定这张桌子的主键是什么。我相信我的错误对你来说是错误的,但对你的问题来说,这并不重要。
-- student_id and class_id are foreign keys, not shown
create table times (
student_id integer not null,
class_id integer not null,
primary key (student_id, class_id),
start_time timestamp not null,
end_time timestamp not null
);
第一名学生在第2和第3课之间有重叠。
insert into times values
(1, 1, '2012-09-01 08:00', '2012-09-01 08:55'),
(1, 2, '2012-09-01 10:00', '2012-09-01 11:55'),
(1, 3, '2012-09-01 11:45', '2012-09-01 12:45');
第二个学生,没有重叠。
insert into times values
(2, 1, '2012-09-01 08:00', '2012-09-01 08:55'),
(2, 2, '2012-09-01 10:00', '2012-09-01 11:55');
第三名学生在1级和2级之间有重叠。
insert into times values
(3, 1, '2012-09-01 08:00', '2012-09-01 10:00'),
(3, 2, '2012-09-01 09:55', '2012-09-01 11:55'),
(3, 3, '2012-09-01 12:00', '2012-09-01 12:55');
如果您的平台符合SQL-92,则可以使用OVERLAPS运算符。 (如果任何dbms支持的断言,您可以以不可能插入重叠类的方式声明表。)
select t1.*
from times t1
inner join times t2 on t1.student_id = t2.student_id
and (t1.class_id <> t2.class_id and t1.start_time <> t2.start_time and t1.end_time <> t2.end_time )
and (t1.start_time, t1.end_time) overlaps (t2.start_time, t2.end_time);
MySQL似乎不支持这一点,因此您可以使用SQL标准委员会中的等效定义。
select t1.*
from times t1
inner join times t2 on t1.student_id = t2.student_id
and (t1.class_id <> t2.class_id and t1.start_time <> t2.start_time and t1.end_time <> t2.end_time )
and (
(t1.start_time > t2.start_time and not (t1.start_time >= t2.end_time and t1.end_time >= t2.end_time))
or
(t2.start_time > t1.start_time and not (t2.start_time >= t1.end_time and t2.end_time >= t1.end_time))
or
(t1.start_time = t2.start_time and (t1.end_time <> t2.end_time or t1.end_time = t2.end_time))
);
我希望连接条件可以为您提供良好的性能,只要您的表被仔细编入索引即可。在您的情况下,您将为单个学生选择行,这应该是非常有选择性的。 (我在我的示例代码中没有这样做。)