我有一个表,用于存储教师可用的约会,允许两种插入:
每小时收费:完全自由地每天为每位老师添加无限制的时间段(只要时间段不重叠即可):15年4月15日,老师可能在10:00、11:00、12:00和16:00有时间段。选择特定的老师时间/时间后,将为一个人服务。
时间段/范围:4月15日,另一位老师可以在10:00至12:00,然后从14:00至18:00上班。一个人按到达顺序得到服务,因此,如果教师在10:00到12:00之间工作,则在此期间到达的所有人员都将按到达顺序(本地队列)参加。
由于必须在搜索中返回所有可用的教师,因此我需要将所有空位与到达范围的顺序保存在同一张表中。这样,我可以通过date_from ASC进行排序,在搜索结果上首先显示第一个可用的广告位。
当前表结构
CREATE TABLE `teacher_slots` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`teacher_id` mediumint(8) unsigned NOT NULL,
`city_id` smallint(5) unsigned NOT NULL,
`subject_id` smallint(5) unsigned NOT NULL,
`date_from` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`date_to` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`status` tinyint(4) NOT NULL DEFAULT '0',
`order_of_arrival` tinyint(1) unsigned NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
KEY `by_hour_idx` (`teacher_id`,`order_of_arrival`,`status`,`city_id`,`subject_id`,`date_from`),
KEY `order_arrival_idx` (`order_of_arrival`,`status`,`city_id`,`subject_id`,`date_from`,`date_to`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
搜索查询
我需要过滤:实际日期时间,city_id,subject_id以及是否有空位(状态= 0)。
对于基于小时的时间,我必须显示每位老师在最近的第一天的所有可用时段(显示给定日期的所有时段,并且同一位老师不能显示超过一天)。(我在mattedgod的帮助下获得了查询)。
对于基于范围的命令(order_of_arrival = 1),我必须显示最接近的可用范围,每位老师仅一次。
第一个查询分别在大约0.10毫秒内运行,第二个查询在0.08毫秒内运行,而UNION ALL平均运行300毫秒。
(
SELECT id, teacher_slots.teacher_id, date_from, date_to, order_of_arrival
FROM teacher_slots
JOIN (
SELECT DATE(MIN(date_from)) as closestDay, teacher_id
FROM teacher_slots
WHERE date_from >= '2014-04-10 08:00:00' AND order_of_arrival = 0
AND status = 0 AND city_id = 6015 AND subject_id = 1
GROUP BY teacher_id
) a ON a.teacher_id = teacher_slots.teacher_id
AND DATE(teacher_slots.date_from) = closestDay
WHERE teacher_slots.date_from >= '2014-04-10 08:00:00'
AND teacher_slots.order_of_arrival = 0
AND teacher_slots.status = 0
AND teacher_slots.city_id = 6015
AND teacher_slots.subject_id = 1
)
UNION ALL
(
SELECT id, teacher_id, date_from, date_to, order_of_arrival
FROM teacher_slots
WHERE order_of_arrival = 1 AND status = 0 AND city_id = 6015 AND subject_id = 1
AND (
(date_from <= '2014-04-10 08:00:00' AND date_to >= '2014-04-10 08:00:00')
OR (date_from >= '2014-04-10 08:00:00')
)
GROUP BY teacher_id
)
ORDER BY date_from ASC;
题
有没有一种方法可以优化UNION,这样我就可以在一个查询(带有IF等)中获得最大〜20ms甚至是基于返回范围+每小时返回的合理响应?
SQL小提琴: http ://www.sqlfiddle.com/#!2/59420/1/0
编辑:
我通过创建一个仅存储日期的字段“ only_date_from”来尝试了一些非规范化,因此可以更改此日期...
DATE(MIN(date_from)) as closestDay / DATE(teacher_slots.date_from) = closestDay
...对此
MIN(only_date_from) as closestDay / teacher_slots.only_date_from = closestDay
它已经为我节省了100毫秒!平均仍为200毫秒。