簡體   English   中英

如何返回按實體分組的最近時間段,但僅針對最近的可用日期,而不是每個可用日期?

[英]How to return the closest time slots grouped by an entity, but just for one closest available day, not every available day?

我有一個表,可以按小時為教師存儲可用的約會,每個教師每天可以自由添加無限的插槽(只要插槽不重疊)。 示例簡化結構:

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列存儲的時間戳。

如何為每位教師顯示第一個最近可用日期的所有可用插槽? 注意:顯示給定日期的所有時段,並且不能為同一位教師顯示超過一天的時間。

示例數據:

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,因為它已經從第10天/ 4月的08:00開始。
  2. 不要顯示id 4,5,6,因為我們發現teacher = 1的最近可用插槽是id的2和3。
  3. 不要顯示id 9,因為對於教師= 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只是為了調試,當然我稍后會優化索引等。

首先,您需要一個查詢來獲得每位教師最近的一天 ,因為每個教師都會有不同的一天 一些假的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()

它顯然沒有經過測試,但它應該給你一般的想法。

無需加入:

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'
;

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM