【问题标题】:Get next available time slot after a certain time in mysql在mysql中的某个时间后获取下一个可用时间段
【发布时间】:2020-02-11 03:32:35
【问题描述】:

我正在尝试通过检查表中的保留时间列表来获取下一个可用时间段。每次预订可以至少增加 1 小时,并且可以持续一整天。例如,如果房间从上午 9 点到 10 点预订,从 12 点到下午 3 点,我试图在上午 9 点之后获得第一个可用位置。现在是上午 10 点。

我可以留在桌子上并获得房间可用性,但不能获得时间段。

这是我的相关架构:

预订

res_id | hotel_id | room_id | res_start | res_end

房间:

room_id | hotel_id | room_name | room_number

这是我目前的查询:

SELECT free_from, free_until
FROM (
  SELECT a.res_end AS free_from,
  (SELECT MIN(c.res_start)
   FROM reservations c
   WHERE c.res_start > a.res_end) as free_until
   and b.res_end > "2019-01-05 11:00:00"
  FROM reservations a
  WHERE NOT EXISTS (
    SELECT 1
    FROM reservations b
    WHERE b.res_start > a.res_end
  )
) as d
ORDER BY free_until-free_from

但是我得到了错误的时间返回。

预期结果:

room_id | room_name | Next available time
1       | "Single"  | 2019-01-05 10:00:00

这是一个 time_slots 表

CREATE TABLE time_slots
    (`slot` time);

INSERT INTO time_slots
    (`slot`)
VALUES
    ('00:00:00'),
    ('01:00:00'),
    ('02:00:00'),
    ('03:00:00'),
    ('04:00:00'),
    ('05:00:00'),
    ('06:00:00'),
    ('07:00:00'),
    ('08:00:00'),
    ('09:00:00'),
    ('10:00:00'),
    ('11:00:00'),
    ('12:00:00'),
    ('13:00:00'),
    ('14:00:00'),
    ('15:00:00'),
    ('16:00:00'),
    ('17:00:00'),
    ('18:00:00'),
    ('19:00:00'),
    ('20:00:00'),
    ('21:00:00'),
    ('22:00:00'),
    ('23:00:00');

【问题讨论】:

  • 如果上一个时段结束,为什么下一个可用时段不在上午 10 点?
  • @Nick 你是对的。我编辑了它

标签: mysql sql database relational-database


【解决方案1】:

您可以使用相关子查询来过滤掉紧随其后的预订;聚合的外部查询返回每个房间较早的可用时间段。

SELECT 
    roo.hotel_id,
    roo.room_id,
    roo.room_name,
    MIN(res.res_end) next_available_time
FROM 
    reservations res
    INNER JOINS rooms roo 
        ON  roo.hotel_id = res.hotel_id 
        AND roo.room_id  = res.room_id
WHERE 
    res.res_end > "2019-01-05 11:00:00"
    AND NOT EXISTS (
        SELECT 1 
        FROM reservations
        WHERE 
            res_start = res.res_end 
            AND hotel_id = res.hotel_id 
            AND room_id  = res.room_id
    ) 
GROUP BY 
    res.hotel_id,
    res.room_id,
    roo.room_name

this DB fiddle 中测试。

我假设连接表时hotel_idroom_id 这两个列都在哪里使用(如果room_id 足够了,那将缩短查询时间)。

【讨论】:

  • 问题是如果 res.res_end 在任何保留之前它不会给出正确的答案,例如 res.res_end > "2018-01-01 01:00:00"跨度>
  • 那么在这种情况下,你想返回什么? "2018-01-01 01:00:00" ?
  • 2018-01-01 07:00:00 因为这是在 2018-01-01 08:00:00 开始预订之前的最后一个可用时间段
  • 您说您想要在给定日期之后的第一个可用时间段。我希望这是2018-01-01 01:00:00,如果在特定时间没有预订房间,不是吗?
  • 我想看看什么时候可以预订房间。所以我想它会在 2018-01-01 08:00:00 之前,最后一个可预订的时段可以是 07:00:00
【解决方案2】:

我认为这个查询会给你你想要的结果。它会查找晚于当前时间且res_endres_start 没有匹配的其他预订的任何预订。

SELECT rm.room_id, rm.room_name, MIN(re.res_end) AS `available from`
FROM reservations re
LEFT JOIN reservations rs ON rs.hotel_id = re.hotel_id AND rs.room_id = re.room_id AND rs.res_start = re.res_end
JOIN rooms rm ON rm.hotel_id = re.hotel_id
WHERE rs.res_id IS NULL AND re.res_end > NOW()
GROUP BY rm.room_id, rm.room_name

输出(给我的小demo on dbfiddle):

room_id     room_name   available from
1           Single      2019-01-06 10:00

更新

此查询使用时隙表来考虑在感兴趣的时间开始时房间内没有预订的情况:

SELECT rm.room_id, rm.room_name,
       MIN(t.slot) AS `available from`
FROM time_slots t
CROSS JOIN rooms rm
LEFT JOIN reservations r ON HOUR(t.slot) BETWEEN HOUR(r.res_start) AND HOUR(r.res_end) - 1 
                        AND DATE(r.res_start) = DATE(@time)
                        AND r.hotel_id = rm.hotel_id
                        AND r.room_id  = rm.room_id
WHERE t.slot > @time AND r.res_id IS NULL
GROUP BY rm.room_id, rm.room_name
ORDER BY rm.room_id

您可以将此查询中的@time 替换为您感兴趣的时间。我更新了我的demo on dbfiddle 来演示查询,您可以调整@time 变量来观察它的工作情况。

【讨论】:

  • 这是正确的答案,但有一个警告。例如,当我设置 re.res_end > "2019-01-05 08:00:00" 时。它显示 10:00 而应该显示 09:00。
  • @HeelMega 你是对的,如果它是免费的,它不会显示当前时间。这需要一些思考......让我编辑我的答案
  • 在问题中为你添加了一个时隙表
  • @HeelMega 我已经更新了我的答案和演示。我认为这应该做你想做的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-12-13
  • 1970-01-01
  • 2018-05-04
  • 1970-01-01
相关资源
最近更新 更多