我有一个简单的房间预订系统,由下表组成:
booking
| id | user | begin | end |
room
| id | name |
booking_map
| id | room_id |
Run Code Online (Sandbox Code Playgroud)
我可以使用以下查询列出当前预订的所有房间:
SELECT booking.id,booking.user,booking.begin,booking.end,room.name
FROM booking,booking_map,room WHERE ((booking.id = booking_map.id)
AND (room.id = booking_map.room_id) AND (begin < now()) AND (end > now()));
Run Code Online (Sandbox Code Playgroud)
但是我如何列出所有免费的房间?
让我们看一些示例数据:
MySQL 5.5.32 架构设置:
CREATE TABLE booking
(`id` int, `user` varchar(2), `begin` datetime, `end` datetime)
;
INSERT INTO booking
(`id`, `user`, `begin`, `end`)
VALUES
(1, 'u1', '2013-02-03 00:00:00', '2013-02-04 00:00:00'),
(2, 'u2', '2013-02-03 00:00:00', '2013-02-06 00:00:00'),
(3, 'u3', '2013-02-05 00:00:00', '2013-02-07 00:00:00'),
(4, 'u4', '2013-02-10 00:00:00', '2013-02-11 00:00:00')
;
CREATE TABLE room
(`id` int, `name` varchar(2))
;
INSERT INTO room
(`id`, `name`)
VALUES
(1, 'r1'),
(2, 'r2'),
(3, 'r3'),
(4, 'r4'),
(5, 'r5'),
(6, 'r6')
;
CREATE TABLE booking_map
(`id` int, `room_id` int)
;
INSERT INTO booking_map
(`id`, `room_id`)
VALUES
(1, 1),
(2, 2),
(3, 3),
(4, 1)
;
Run Code Online (Sandbox Code Playgroud)
首先,我们需要找到当天的所有预订:
查询 1:
SELECT *
FROM booking
WHERE begin <= '2013-02-04'
AND end >= '2013-02-04'
Run Code Online (Sandbox Code Playgroud)
[结果][2]:
| ID | USER | BEGIN | END |
|----|------|---------------------------------|---------------------------------|
| 1 | u1 | February, 03 2013 00:00:00+0000 | February, 04 2013 00:00:00+0000 |
| 2 | u2 | February, 03 2013 00:00:00+0000 | February, 06 2013 00:00:00+0000 |
Run Code Online (Sandbox Code Playgroud)
或者说真的,我们需要一份当天所有预订房间的清单。为此,我们只需将预订加入到预订地图中:
查询 2:
SELECT m.room_id
FROM booking AS b
JOIN booking_map AS m
ON b.id = m.id
WHERE b.begin <= '2013-02-04'
AND b.end >= '2013-02-04'
Run Code Online (Sandbox Code Playgroud)
[结果][3]:
| ROOM_ID |
|---------|
| 1 |
| 2 |
Run Code Online (Sandbox Code Playgroud)
现在,有了这些信息,我们可以返回所有不在预订房间列表中的房间:
查询 3:
SELECT *
FROM room AS r
WHERE r.id NOT IN(
SELECT m.room_id
FROM booking AS b
JOIN booking_map AS m
ON b.id = m.id
WHERE b.begin <= '2013-02-04'
AND b.end >= '2013-02-04'
)
Run Code Online (Sandbox Code Playgroud)
[结果][4]:
| ID | NAME |
|----|------|
| 3 | r3 |
| 4 | r4 |
| 5 | r5 |
| 6 | r6 |
Run Code Online (Sandbox Code Playgroud)