SQL - 为预订系统寻找空闲时段
SQL - Find free slots for booking system
我得到了一个简单的 mysql table 已预订的房间。这里的 sql 结构:
CREATE TABLE Rooms (
`ID` int, `Description` varchar(50)
);
INSERT INTO Rooms values
(123, 'Room in Frankfurt'),
(234, 'Room in Wiesbaden'),
(245, 'Room in Darmstadt');
CREATE TABLE Bookings (
`ID` int, `StartTime` datetime, `EndTime` datetime, `post_ID` int
);
INSERT INTO Bookings
(`ID`, `StartTime`, `EndTime`, `post_ID`)
VALUES
(1, '2018-01-05', '2018-04-05', 123),
(2, '2018-08-01', '2018-10-01', 123),
(3, '2019-02-01', '2019-06-01', 123),
(4, '2018-02-01', '2018-06-01', 234),
(5, '2018-08-01', '2018-09-01', 294),
(6, '2018-09-01', '2018-11-30', 234),
(7, '2018-11-01', '2018-12-30', 294)
;
在此 table 中,我们可以看到所有房间的所有预订。我的问题是找到 SQL 查询来查找房间的空闲位置。用户可以提供这些参数:
- 最早入住的日期(例如:2018-10-01)
- 最近一次签到的日期(例如:2018-10-15)
- 最长期限(以月为单位)(例如:3 个月)
所以用户需要3个月的房间,从01-15开始。 2018 年 10 月。
我该怎么做?实在是看不懂。
谢谢!
我假设你有某种 Rooms
table
http://sqlfiddle.com/#!9/fe977/1
SELECT r.*
FROM rooms r
LEFT JOIN Bookings b
ON r.id = b.post_id
AND (
(b.StartTime <= '2018-10-01'
AND b.EndTime >= '2018-10-01')
OR
(b.StartTime >= '2018-10-01'
AND b.StartTime <= '2018-10-15')
)
WHERE b.id IS NULL
更新 我仍然不确定我是否达到了您的目标。但这是另一种方法。如果您希望开始日期灵活,我建议为一年中的所有日期设置 calendar
table。这将允许在您 运行 查询时避免不必要的计算。
这是一个fiddle:http://sqlfiddle.com/#!9/29926/3
SELECT r.*,
c.date
FROM rooms r
LEFT JOIN calendar c
ON c.date BETWEEN '2018-10-01' AND '2018-10-15'
LEFT JOIN Bookings b
ON r.id = b.post_id
AND (
(b.StartTime <= c.date
AND b.EndTime >= c.date)
OR
(b.StartTime >= c.date
AND b.StartTime <= (c.date + INTERVAL 3 MONTH))
)
WHERE b.id IS NULL
更新 2 结合@Strawberry 的回答我想我们可以将查询修改为:
http://sqlfiddle.com/#!9/29926/5
SELECT r.*,
c.date
FROM rooms r
LEFT JOIN calendar c
ON c.date BETWEEN '2018-10-01' AND '2018-10-15'
LEFT JOIN Bookings b
ON r.id = b.post_id
AND b.StartTime <= (c.date + INTERVAL 3 MONTH)
AND b.EndTime >= c.date
WHERE b.id IS NULL
首先,让我们看看每个房间的空闲间隔:
select room_ID, a.EndTime, b.StartTime
from Bookings a
join (select c.StartTime
from Bookings c
where c.room_ID = a.room_ID and
not exists (select 1
from Bookings d
where d.room_ID = c.room_ID and d.StartTime > a.EndTime and d.StartTime < c.StartTime)) b;
这应该 union
与第一个元素的 now()
和 StartTime
之间的间隔进行编辑。通过这种方式,您将获得一个结果,您可以从中得出问题的答案。我不打算为您的家庭作业实施解决方案,这个答案旨在作为解决方案的起点。
Supplied criteria:
1. a date for the earliest check-in (ex: 2018-10-01)
2. a date for the latest check-in (ex: 2018-10-15)
3. a maximum period in months (example: 3 months)
这是一个仅考虑条件 1 和 3 的解决方案...
SELECT r.*
FROM rooms r
LEFT
JOIN bookings b
ON b.post_id = r.id
AND b.starttime < '2018-10-01' + INTERVAL 3 MONTH
AND b.endtime > '2018-10-01'
WHERE b.id IS NULL;
+------+-------------------+
| ID | Description |
+------+-------------------+
| 123 | Room in Frankfurt |
| 245 | Room in Darmstadt |
+------+-------------------+
但你真正的问题似乎是:
哪些房间在 10 月 1 日开始的 45 天内有“3 个月的可用性”。这是一个略有不同(而且我认为更复杂)的问题。
我得到了一个简单的 mysql table 已预订的房间。这里的 sql 结构:
CREATE TABLE Rooms (
`ID` int, `Description` varchar(50)
);
INSERT INTO Rooms values
(123, 'Room in Frankfurt'),
(234, 'Room in Wiesbaden'),
(245, 'Room in Darmstadt');
CREATE TABLE Bookings (
`ID` int, `StartTime` datetime, `EndTime` datetime, `post_ID` int
);
INSERT INTO Bookings
(`ID`, `StartTime`, `EndTime`, `post_ID`)
VALUES
(1, '2018-01-05', '2018-04-05', 123),
(2, '2018-08-01', '2018-10-01', 123),
(3, '2019-02-01', '2019-06-01', 123),
(4, '2018-02-01', '2018-06-01', 234),
(5, '2018-08-01', '2018-09-01', 294),
(6, '2018-09-01', '2018-11-30', 234),
(7, '2018-11-01', '2018-12-30', 294)
;
在此 table 中,我们可以看到所有房间的所有预订。我的问题是找到 SQL 查询来查找房间的空闲位置。用户可以提供这些参数:
- 最早入住的日期(例如:2018-10-01)
- 最近一次签到的日期(例如:2018-10-15)
- 最长期限(以月为单位)(例如:3 个月)
所以用户需要3个月的房间,从01-15开始。 2018 年 10 月。
我该怎么做?实在是看不懂。
谢谢!
我假设你有某种 Rooms
table
http://sqlfiddle.com/#!9/fe977/1
SELECT r.*
FROM rooms r
LEFT JOIN Bookings b
ON r.id = b.post_id
AND (
(b.StartTime <= '2018-10-01'
AND b.EndTime >= '2018-10-01')
OR
(b.StartTime >= '2018-10-01'
AND b.StartTime <= '2018-10-15')
)
WHERE b.id IS NULL
更新 我仍然不确定我是否达到了您的目标。但这是另一种方法。如果您希望开始日期灵活,我建议为一年中的所有日期设置 calendar
table。这将允许在您 运行 查询时避免不必要的计算。
这是一个fiddle:http://sqlfiddle.com/#!9/29926/3
SELECT r.*,
c.date
FROM rooms r
LEFT JOIN calendar c
ON c.date BETWEEN '2018-10-01' AND '2018-10-15'
LEFT JOIN Bookings b
ON r.id = b.post_id
AND (
(b.StartTime <= c.date
AND b.EndTime >= c.date)
OR
(b.StartTime >= c.date
AND b.StartTime <= (c.date + INTERVAL 3 MONTH))
)
WHERE b.id IS NULL
更新 2 结合@Strawberry 的回答我想我们可以将查询修改为:
http://sqlfiddle.com/#!9/29926/5
SELECT r.*,
c.date
FROM rooms r
LEFT JOIN calendar c
ON c.date BETWEEN '2018-10-01' AND '2018-10-15'
LEFT JOIN Bookings b
ON r.id = b.post_id
AND b.StartTime <= (c.date + INTERVAL 3 MONTH)
AND b.EndTime >= c.date
WHERE b.id IS NULL
首先,让我们看看每个房间的空闲间隔:
select room_ID, a.EndTime, b.StartTime
from Bookings a
join (select c.StartTime
from Bookings c
where c.room_ID = a.room_ID and
not exists (select 1
from Bookings d
where d.room_ID = c.room_ID and d.StartTime > a.EndTime and d.StartTime < c.StartTime)) b;
这应该 union
与第一个元素的 now()
和 StartTime
之间的间隔进行编辑。通过这种方式,您将获得一个结果,您可以从中得出问题的答案。我不打算为您的家庭作业实施解决方案,这个答案旨在作为解决方案的起点。
Supplied criteria:
1. a date for the earliest check-in (ex: 2018-10-01)
2. a date for the latest check-in (ex: 2018-10-15)
3. a maximum period in months (example: 3 months)
这是一个仅考虑条件 1 和 3 的解决方案...
SELECT r.*
FROM rooms r
LEFT
JOIN bookings b
ON b.post_id = r.id
AND b.starttime < '2018-10-01' + INTERVAL 3 MONTH
AND b.endtime > '2018-10-01'
WHERE b.id IS NULL;
+------+-------------------+
| ID | Description |
+------+-------------------+
| 123 | Room in Frankfurt |
| 245 | Room in Darmstadt |
+------+-------------------+
但你真正的问题似乎是:
哪些房间在 10 月 1 日开始的 45 天内有“3 个月的可用性”。这是一个略有不同(而且我认为更复杂)的问题。