Sql的房间供应情况

时间:2015-01-16 15:39:15

标签: php mysql sql

我有以下表结构

房间

||| room_id ||| name |||
|||    1    ||| best |||
|||    2    ||| best |||
|||    3    ||| best |||
|||    4    ||| best |||

预订

||| room_id ||| date_start |||   date_end     |||
|||    1    ||| 2015-01-10 |||  2015-01-15    |||
|||    2    ||| 2015-01-10 |||  2015-01-18    |||
|||    3    ||| 2015-01-05 |||  2015-01-10    |||
|||    4    ||| 2015-01-02 |||  2015-01-05    |||

我想要的是如果用户搜索 date_start = 2015-01-10 date_end = 2015-01-14

我想展示那些日子的可用房间。

这是我到目前为止所尝试的

SELECT r.*
FROM rooms r
WHERE r.room_id NOT IN (
    SELECT b.room_id FROM bookings b
    WHERE (b.date_start   <= '$data[datestart]' AND b.date_end >= '$data[dateend]'))
谢谢你!

3 个答案:

答案 0 :(得分:1)

看看可能性:

x/y = your query's "find available for these days"
a/b = various records' start/end in your db

以下是所有可能的变体:

   a    b
---+----+---
xy |    |     // no overlap
x  | y  |     // partial overlap
x  |    | y   // complete overlap
   | xy |     // complete overlap
   | x  | y   // partial overlap
   |    | xy  // no overlap

一旦你关闭了逻辑,你最终会得到

(y < a) || (x > b)   // no overlap at all

答案 1 :(得分:1)

如果您正在考虑日期范围,例如01/10和01/14,则有三种情况:房间不可用:

  • 某人的开始日期为01/10至01/14
  • 某人的结束日期为01/10至01/14
  • 有人在01/10之前有一个开始日期,在01/14之后有一个结束日期。

因此,对于前两个,您可以使用BETWEEN运算符查看日期是否在范围内,而其他日期则使用大于或小于。

我建议的是写一个查询来获取不可用的房间:

SELECT r.*
FROM room r
JOIN bookings b ON b.room_id = r.room_id
WHERE b.date_start BETWEEN '2015-01-10' AND '2015-01-14'
  OR b.date_end BETWEEN '2015-01-10' AND '2015-01-14'
  OR (b.date_start < '2015-01-10' AND b.date_end > '2015-01-14');

然后您可以使用NOT IN从rooms_table中选择不在此禁止列表中的任何房间:

SELECT r.*
FROM room r
WHERE r.room_id NOT IN(
  SELECT r.room_id
  FROM room r
  JOIN bookings b ON b.room_id = r.room_id
  WHERE b.date_start BETWEEN '2015-01-10' AND '2015-01-14'
    OR b.date_end BETWEEN '2015-01-10' AND '2015-01-14'
    OR (b.date_start < '2015-01-10' AND b.date_end > '2015-01-14'));

如果你想避免使用子查询,你可以忽略每个条件来获得可用的房间:

SELECT r.*
FROM room r
JOIN bookings b ON b.room_id = r.room_id
WHERE b.date_start NOT BETWEEN '2015-01-10' AND '2015-01-14'
  AND b.date_end NOT BETWEEN '2015-01-10' AND '2015-01-14'
  AND (b.date_start >= '2015-01-10' OR b.date_end <= '2015-01-14');

这是一个包含所有三个示例的SQL Fiddle

答案 2 :(得分:0)

SELECT rooms.room_id, rooms.name FROM rooms
INNER JOIN bookings
ON rooms.room_id =bookings.room_id 
WHERE bookings.date_start >= DATE('2015-01-10') AND bookings.date_end <= DATE('2015-01-14');