我想使用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
和$end
是从文本框输入的。用户首先填写开始输入和结束输入,点击搜索后,它将显示任何可用的房间。从我的查询中,如果m_order中存在的示例数据是:room_id->1; start-> 2015-05-13; end-> 2015-05-16
然后当我填写$start
时: 2015-05-14 和$end
: 2015-05-15 ,它正常工作,room_id没有。 1将不会显示,但如果我将日期$start
填入: 2015-05-14 和$end
,则: 2015-05-19 ,room_id没有。 1仍然显示,但必须不是因为客户仍然使用2015-05-13至2015-05-16
那么,如何修复我的查询以显示任何可用的房间?
答案 0 :(得分:3)
我认为你可能采取了错误的做法。您想要查找整个期间可用的房间,这意味着如果有任何预订的开始日期或结束日期,包含您要查找的期间的开始日期或结束日期,则必须是拒绝。
我们可以使用where not exists
来完成此任务。例如,检查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')
);
作为第二个选项,您还可以left join
到order_room
表,将日期范围放在连接条件中,然后检查order_room
值为{{{1}的行1}}。
null
this demo也有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;
选项,显示结果相同。这种方法的优势在于您可以获得两个有意义的结果 - 它向您显示绝对可用的房间,如果您删除left join
条款,它还会显示与其他房间冲突的预订时间。 / p>
如果您想在与其他预订退房/入住日重叠的同一天办理入住/退房手续,我们只需要将日期范围修改一天,如下所示:
where
OR
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')
);
答案 1 :(得分:0)
房间ID 1将显示第二个查询,因为输入的结束日期在order_bookend之后,所以我想你需要检查我们之间输入的开始日期。预订开始和结束,或输入的结束日期在预订开始和结束之间
WHERE ('$start'>= order_bookstart OR '$start'< order_bookend) OR
('$end'>= order_bookstart OR '$end'< order_bookend)
答案 2 :(得分:0)
考虑以下
1 2 3 4 5 6 7 8 9
A |---|
B |-----|
C |----|
D |-----------|
重叠测试比pala简单,其他人似乎很欣赏。
事件B与事件A重叠,因为事件B在事件A结束之前开始,并在事件A开始之后结束。
事件C不会与事件B重叠,因为事件B在事件B开始后结束,但它在事件B结束后开始
事件D与所有其他事件重叠,因为事件D在所有其他事件结束之前开始,并在所有其他事件开始之后结束。
所以对重叠的测试很简单:
y_start < x_end AND y_end > x_start
答案 3 :(得分:-1)
为了使房间不包含在搜索结果中,WHERE条件应涵盖以下情况:
a) bookstart----start--------bookend-------end------------
b) -------------start--------bookstart-----end-----bookend
c) -------------start--bookstart--bookend--end------------
d) bookstart----start----------------------end-----bookend
换句话说, bookstart 或 bookend 介于开始和结束之间(案例a-c) ,或 bookstart 在开始之前,书挡在结束之后(案例d):
所以正确的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)