在 mysql 中的特定时间后获取下一个可用时间段
Get next available time slot after a certain time in mysql
我正在尝试通过检查 table 中的保留时间列表来获取下一个可用时间段。每次预订最少可以增加 1 小时,并且可以持续一整天。例如,如果房间是从上午 9 点到 10 点,以及从中午 12 点到下午 3 点预订的,我想在上午 9 点之后获得第一个可用空位。现在是上午 10 点。
我可以在 table 上离开加入并获得房间可用性,但不是时间段。
这是我的相关架构:
预订
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_slotstable
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');
您可以使用相关子查询来过滤掉紧接着另一个预订的预订;聚合外部查询 returns 每个房间的较早可用时间段。
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_id
和 room_id
列(如果 room_id
就足够了,那会稍微缩短查询)。
我想这个查询会给你想要的结果。它会查找晚于当前时间的任何预订,其 res_end
没有匹配的 res_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
更新
此查询使用时间段 table 来考虑在感兴趣的时间开始时房间内没有预订的情况:
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
变量来观察它的工作。
我正在尝试通过检查 table 中的保留时间列表来获取下一个可用时间段。每次预订最少可以增加 1 小时,并且可以持续一整天。例如,如果房间是从上午 9 点到 10 点,以及从中午 12 点到下午 3 点预订的,我想在上午 9 点之后获得第一个可用空位。现在是上午 10 点。
我可以在 table 上离开加入并获得房间可用性,但不是时间段。
这是我的相关架构:
预订
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_slotstable
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');
您可以使用相关子查询来过滤掉紧接着另一个预订的预订;聚合外部查询 returns 每个房间的较早可用时间段。
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_id
和 room_id
列(如果 room_id
就足够了,那会稍微缩短查询)。
我想这个查询会给你想要的结果。它会查找晚于当前时间的任何预订,其 res_end
没有匹配的 res_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
更新
此查询使用时间段 table 来考虑在感兴趣的时间开始时房间内没有预订的情况:
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
变量来观察它的工作。