繁体   English   中英

用于房间可用性的SQL

[英]Sql for room availability

我有以下表格结构

房间

||| 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-10date_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]'))

谢谢!

看一下可能性:

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

如果考虑的日期范围为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

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');

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM