【问题标题】:Sql for room availability用于房间可用性的 Sql
【发布时间】:2023-03-23 09:20:01
【问题描述】:

我有以下表结构

房间桌子

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

谢谢!

【问题讨论】:

  • 你能分享你的尝试吗?
  • MySQL 是否支持 OVERLAPS?
  • @jayBlanchard 我添加了

标签: php mysql sql


【解决方案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

【讨论】:

  • 这是一种有趣的思维方式,这是一种已知的方法(如果是,它叫什么?),还是只是您分析 OP 问题的方式?谢谢
  • 如果您允许在上午退房的同一天下午入住,那就是 (y &lt;= a) || (x &gt;= b)
  • @joe:它基本上只是布尔代数。为重叠图的每一行写一个表达式,将所有表达式放在一起,然后减少它们。
  • x小于a,y大于b的情况呢?
  • @McAdam331:哎呀,对...忘记将那个添加到图表中(已修复...),但仍会被排除在外
【解决方案2】:

如果您正在考虑 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'));

如果你想避免子查询,你可以否定你的每个条件来获得 available 个房间:

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,包含所有三个示例。

【讨论】:

  • 嗨,谢谢!..但我有一个小问题,我所有的预订信息都在另一个单独的表格中,例如(客户姓名,电子邮件)..如何也可以从该表格中选择所有信息?跨度>
  • 您可以在关联预订表和客户表的列上添加另一个联接。
  • 它与 booking_id 相关,请告诉我在哪里可以包含它?..谢谢
【解决方案3】:
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');

【讨论】:

  • 如果有人预订了 01-11 到 01-12 的房间怎么办?该房间将不可用,但由您的查询返回。
  • 真的,这就像检查两个日期之间的预订,没有空房。
  • 嘿,抱歉,我没有考虑。我正在考虑所提供的具体细节。谢谢
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-06-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-06-23
  • 1970-01-01
相关资源
最近更新 更多