我有一个SQL查询,用于查找特定日期后最近的空闲时间。如何在此日期之前查找日期?

时间:2015-11-13 11:00:57

标签: mysql sql

这是对我之前提问A query for finding the nearest free time slot in mysql - why it doesn't work?

的跟进

基本上我有一张桌子:

id  |      start_time       |  duration
 1  |  2015-10-21 19:41:35  |    15
 2  |  2015-10-21 19:41:50  |    15
 3  |  2015-10-21 19:42:05  |    15
 4  |  2015-10-21 19:42:35  |    15
etc.

它包含事件start_time及其持续时间。我请求帮助找到可以在现有事件之间放置事件的最近时间段。 @Richard提出了一个完美的答案https://stackoverflow.com/a/33689786/3766930并提出了一个问题:

SELECT (a.start_time + INTERVAL a.duration SECOND) AS free_after FROM notes a
WHERE
NOT EXISTS ( SELECT 1 FROM notes b WHERE b.start_time
BETWEEN (a.start_time + INTERVAL a.duration SECOND) AND
(a.start_time + INTERVAL a.duration SECOND) + INTERVAL 15 SECOND - INTERVAL 1 MICROSECOND) AND
(a.start_time + INTERVAL a.duration SECOND) BETWEEN '2015-10-21 19:41:30' AND '2015-10-21 19:43:50'

效果很好。

现在我想知道是否有可能在现有日期之间找到最合适的日期,而且也就在它们之前。

例如:我将begin_date设置为2015-10-21 16:00:00,将end_date设置为2015-10-21 21:00:00。目前,@ Richard的查询结果为2015-10-21 19:42:20。但有没有办法创建一个查询,在这个结果中,2015-10-21 19:41:20将返回到已经在数据库中的第一个日期最近的查询?

3 个答案:

答案 0 :(得分:4)

一个简单的解决方案是使用date_sub和order by语句,将结果限制为仅显示1条记录。

结果如下:

SELECT date_sub(start_time, interval duration second) as free_before FROM `notes` where start_time>'2015-10-21 16:00:00' order by start_time asc limit 1

为您加分

使用@Richard提供的上一个解决方案。将所有这些放在一起以显示1个表中的所有空闲时间可能会产生以下结果:

select * from (SELECT date_sub(start_time, interval duration second) as free_times FROM `notes` where start_time>'2015-10-21 16:00:00' order by start_time asc limit 1) a
union
(SELECT (a.start_time + INTERVAL a.duration SECOND) AS free_times FROM notes a
WHERE
NOT EXISTS ( SELECT 1 FROM notes b WHERE b.start_time
BETWEEN (a.start_time + INTERVAL a.duration SECOND) AND
(a.start_time + INTERVAL a.duration SECOND) + INTERVAL 15 SECOND - INTERVAL 1 MICROSECOND) AND
(a.start_time + INTERVAL a.duration SECOND) BETWEEN '2015-10-21 19:41:30' AND '2015-10-21 19:43:50')

修改

我只会写我的部分查询。另一部分工作正常,只有你想让我改变它我会(永远不会修复没有破坏的东西)

如果你想要10秒的间隔 - > <>

SELECT date_sub(start_time, interval 10 second) as free_times FROM `notes` where start_time>'2015-10-21 16:00:00' order by start_time asc limit 1

如果您想要15秒的间隔 - > <>

SELECT date_sub(start_time, interval 15 second) as free_times FROM `notes` where start_time>'2015-10-21 16:00:00' order by start_time asc limit 1

在这种情况下,您必须相应地更改start_time和持续时间。

答案 1 :(得分:1)

这对你有用吗?

假设:

select * from notes;
+----+---------------------+----------+
| id | start_time          | duration |
+----+---------------------+----------+
|  1 | 2015-11-17 10:10:10 |       15 |
|  2 | 2015-11-17 10:20:40 |       15 |
|  3 | 2015-11-17 10:30:00 |       15 |
+----+---------------------+----------+

结果:

select (start_time - interval 15 second) as earlier_date
    from notes
    where start_time > '2015-11-17 10:15:00' 
       AND start_time < '2015-11-17 10:25:00' 
    order by start_time 
    limit 1;

+---------------------+
| earlier_date        |
+---------------------+
| 2015-11-17 10:20:25 |
+---------------------+

重要提示:此示例并未注意可能会立即落在搜索窗口前的条目(因为您的示例并未包含任何内容)。如果在搜索窗口之前存在冲突条目,则此查询按创建重叠。

答案 2 :(得分:-2)

拿你的基表并插入一个假行,这是一个最小的开始时间并减去15秒。

所以不用注释,而是使用这样的子查询:

    SELECT 
            MIN(start_time) - INTERVAL 15 seconds AS start_time,
            0 AS duration
    FROM notes

    UNION ALL

    SELECT start_time, duration
    FROM notes