简体   繁体   English

SQL预订酒店房间

[英]SQL reservation hotel room

I want to create a reservation hotel's room using PHP, and to see any available rooms, I use query like this: 我想使用PHP创建预订酒店的房间,并查看任何可用的房间,我使用如下查询:

SELECT * FROM m_room WHERE room_id NOT IN 
(SELECT order_room FROM m_order WHERE 
'$start' >= order_bookstart AND '$end' <  order_bookend) 
ORDER BY room_name

$start and $end is input from a textbox. $start$end是从文本框中输入的。 User first fill the start input and end input, after click search, it will show any available rooms. 用户首先填写开始输入和结束输入,单击搜索后,它将显示所有可用房间。 From my query, If my example data that exist in m_order is: room_id->1; start-> 2015-05-13; end-> 2015-05-16 根据我的查询,如果我的示例数据存在于m_order中,则为: room_id->1; start-> 2015-05-13; end-> 2015-05-16 room_id->1; start-> 2015-05-13; end-> 2015-05-16

then when I fill $start with : 2015-05-14 and $end with : 2015-05-15 , it works normally, room_id no. 然后,当我用$start 2015start和2015-05-15分别填充$start$end时: 2015-05-15 ,它可以正常工作,room_id号。 1 won't shows up, but if I fill the date $start with : 2015-05-14 and $end with: 2015-05-19 , room_id no. 1不会显示,但是如果我将日期$start填入: 2015-05-14,$end填入日期: 2015-05-19 ,则room_id为no。 1 still shows up, which must be not because still used by a client from 2015-05-13 till 2015-05-16 仍然显示1,这一定不是因为从2015年5月13日到2015年5月16日客户仍在使用

So, how to fix my query to show any available rooms? 那么, 如何解决我的查询以显示任何可用房间?

I think you might be taking the wrong approach. 我认为您可能采取了错误的方法。 You want to find rooms which are available for the whole period, which means if there is ANY booking that has either a start, or an end date, that encompasses either the start or end date of the period you are looking for, it must be rejected. 您想找到整个期间都可以使用的房间,这意味着如果有任何包含开始或结束日期的预订,其中包含您要查找的期间的开始或结束日期,则必须是被拒绝。

We can use where not exists to accomplish this. 我们可以使用where not exists来完成此任务。 For example, for checking if there is a room available from the 14th to the 15th: 例如,要检查从14日到15日是否有可用的房间:

select *
  from m_room
  where not exists (
    select 1
      from order_room
      where room_id = m_room.room_id
        and ('2015-05-14' between start_date and end_date   
          or '2015-05-15' between start_date and end_date
          or start_date between '2015-05-14' and '2015-05-15')
   );

demo here 在这里演示

As a second option, you could also left join to the order_room table, putting the date range in the join criteria, and then checking for rows where the order_room values are null . 第二种选择是,您还可以将order_room left joinorder_room表中,将日期范围放入order_room条件中,然后检查order_room值为null

select *
  from m_room
    left join order_room
      on m_room.room_id = order_room.room_id
        and ('2015-05-14' between start_date and end_date
          or '2015-05-15' between start_date and end_date
          or start_date between '2015-05-14' and '2015-05-15')
  where start_date is null;

this demo has the left join option as well, showing the results are equivalent. 该演示还具有left join选项,显示结果是等效的。 This method has the advantage that you get two meaningful results - it shows you the rooms that are definitely available, and if you remove the where clause, it will also show you the booking times that conflict for the other rooms. 此方法的优点是您得到两个有意义的结果-向您显示确实可用的房间,并且如果删除where子句,还将向您显示与其他房间冲突的预订时间。

If you want to allow check-in/check-out on the same day that overlaps another bookings check-out/check-in days, we just need to modify the date range by one day, like so: 如果您想允许在同一天的办理入住/退房手续与另一笔预订的办理入住/退房日子重叠,我们只需要将日期范围修改一天,就像这样:

select *
  from m_room
  where not exists (
    select 1
      from order_room
      where room_id = m_room.room_id
        and ('2015-05-16' between start_date and end_date - interval 1 day
          or '2015-05-20' between start_date - interval 1 day and end_date
          or start_date between '2015-05-16' and '2015-05-20')
   );

OR 要么

select *
  from m_room
    left join order_room
      on m_room.room_id = order_room.room_id
        and ('2015-05-16' between start_date and end_date - interval 1 day
          or '2015-05-20' between start_date - interval 1 day and end_date
          or start_date between '2015-05-16' and '2015-05-20')
  where start_date is null;

Room ID 1 will show up with the second query because the end date entered is after the order_bookend, so I'd imagine you will need to check the start date entered us between. 房间ID 1将与第二个查询一起显示,因为输入的结束日期在order_bookend之后,因此我想您需要检查在我们之间输入的开始日期。 A booking start and end, or the entered end date is between a booking start and end 预订开始和结束,或输入的结束日期在预订开始和结束之间

WHERE ('$start'>= order_bookstart OR '$start'< order_bookend) OR 
('$end'>= order_bookstart OR '$end'< order_bookend)

Consider the following 考虑以下

  1 2 3 4 5 6 7 8 9 

A |---|

B    |-----|

C            |----|

D   |-----------|

The test for overlaps is simpler than pala and others seem to appreciate. 重叠测试比pala更简单,其他人似乎很欣赏。

Event B overlaps event A because event B starts before event A ends, and ends after event A starts. 事件B与事件A重叠,因为事件B在事件A结束之前开始,而在事件A开始之后结束。

Event C does NOT overlap event B because although event C ends after event B starts, it starts after event B ends 事件C与事件B不重叠,因为尽管事件C在事件B开始后结束,但它在事件B结束后开始

Event D overlaps all the other events because event D starts before all of the other events end, and ends after all the other events start. 事件D与所有其他事件重叠,因为事件D在所有其他事件结束之前开始,并在所有其他事件开始之后结束。

So the test for overlaps is simply: 因此,重叠的测试很简单:

y_start < x_end AND y_end > x_start 

In order for the room to not be included in the search results, the WHERE condition should cover the following cases: 为了使房间不包含在搜索结果中,WHERE条件应涵盖以下情况:

a) bookstart----start--------bookend-------end------------

b) -------------start--------bookstart-----end-----bookend

c) -------------start--bookstart--bookend--end------------

d) bookstart----start----------------------end-----bookend

In other words, either bookstart or bookend is between start and end (cases a - c), or bookstart is before start and bookend is after end (case d): 换句话说, bookstartbookend开始结束之间(例a-c),或者bookstart开始之前,而bookend结束之后(例d):

So the correct SQL should look like this: 因此正确的SQL应该如下所示:

WHERE (order_bookstart >= $start AND order_bookstart < $end) OR
(order_bookend >= $start AND order_bookend < $end) OR 
(order_bookstart < $start AND order_bookend > $end)

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

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