查询:选择所有未预订的房间

Mar*_*ter 2 mysql

我有一个简单的房间预订系统,由下表组成:

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)

但是我如何列出所有免费的房间?

Seb*_*ine 5

让我们看一些示例数据:

SQL小提琴

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)