4

我有一个表格,可以存储教师的可用约会,按小时计算,可以完全自由地为每位教师每天添加无限的插槽(只要插槽不重叠)。示例简化结构:

CREATE TABLE time_slots (
  id int(10) unsigned NOT NULL AUTO_INCREMENT,
  teacher_id mediumint(8) unsigned NOT NULL,
  slot bigint(20) unsigned NOT NULL DEFAULT '0',
 );

slot列存储 slot的时间戳。

如何为每位教师显示最接近的第一个可用日期的所有可用位置?注意:显示给定一天的所有时间段,同一老师不能显示超过一天。

示例数据:

PS:使用 datetime 只是为了使事情更具可读性。

+----+------------+------------------+
| id | teacher_id | slot             |
+----+------------+------------------+
| 1  | 1          | 2013-04-10 08:00 |
| 2  | 1          | 2013-04-10 09:00 |
| 3  | 1          | 2013-04-10 09:30 |
| 4  | 1          | 2013-04-11 08:00 |
| 5  | 1          | 2013-04-11 09:00 |
| 6  | 1          | 2013-04-11 10:30 |
| 7  | 2          | 2013-04-12 07:00 |
| 8  | 2          | 2013-04-12 09:00 |
| 9  | 2          | 2013-04-14 08:00 |
+----+------------+------------------+

预期结果:

假设在2013-04-10 08:30进行搜索,返回的结果必须是:

+----+------------+------------------+
| id | teacher_id | slot             |
+----+------------+------------------+
| 2  | 1          | 2013-04-10 09:00 |
| 3  | 1          | 2013-04-10 09:30 |
| 7  | 2          | 2013-04-12 07:00 |
| 8  | 2          | 2013-04-12 09:00 |
+----+------------+------------------+
  1. 不要显示 id 1,因为从 4 月 10 日开始已经过了 08:00。
  2. 不要显示 id 4、5、6,因为我们发现teacher = 1 的最接近的可用插槽是 id 的 2 和 3。
  3. 不要显示 id 9,因为对于 teacher = 2,最接近的可用插槽是 7 和 8,所以不要改天返回。

我试过的

我很难提出查询,我只是提出了这个基本查询,但它没有假设只获得第一个可用天,当然它不会返回给定日期的所有可用插槽。每个教师只返回 1 个插槽:

SELECT id, teacher_id, FROM_UNIXTIME(slot)
FROM time_slots
WHERE slot >= [Actual timestamp]
GROUP BY DATE(FROM_UNIXTIME(slot))
ORDER BY slot, teacher_id ASC

注意:我在这里使用 FROM_UNIXTIME 只是为了调试,当然我稍后会优化索引等。

4

2 回答 2

2

首先,您需要一个查询来获取每个老师最近的一天,因为这对于每个老师来说都是不同的。一些伪 SQL 在这里这样做:

SELECT
  MIN(DATE(slot)) as closestDay,
  teacher_id
FROM time_slots
WHERE slot >= NOW()
GROUP BY teacher_id

然后进行该查询并使用结果显示每天的所有可用插槽

SELECT 
   id,
   time_slots.teacher_id,
   FROM_UNIXTIMESTAMP(slot)
FROM time_slots
JOIN (
    SELECT
      MIN(DATE(slot)) as closestDay,
      teacher_id
    FROM time_slots
    WHERE slot >= NOW()
    GROUP BY teacher_id
) a
ON a.teacher_id = time_slots.teacher_id
  AND DATE(time_slots.slot) = closestDay
WHERE time_slots.slot >= NOW()

它显然没有经过测试,但它应该给你一个大致的想法。

于 2013-04-10T19:20:45.497 回答
1

无需加入:

drop table if exists time_slots;
CREATE TABLE time_slots (
  id int(10) unsigned NOT NULL AUTO_INCREMENT primary key,
  teacher_id mediumint(8) unsigned NOT NULL,
  slot datetime 
 );
insert into time_slots values 
('1','1','2013-04-10 08:00'),
('2','1','2013-04-10 09:00'),
('3','1','2013-04-10 09:30'),
('4','1','2013-04-11 08:00'),
('5','1','2013-04-11 09:00'),
('6','1','2013-04-11 10:30'),
('7','2','2013-04-12 07:00'),
('8','2','2013-04-12 09:00'),
('9','2','2013-04-14 08:00');

select * from time_slots 
where (teacher_id, date(slot)) in
(select teacher_id, date(min(slot)) from time_slots where slot >= '2013-04-10 08:30' group by teacher_id)
having slot >= '2013-04-10 08:30'
;
于 2013-04-10T19:33:04.483 回答