我的 sql 数据库中有 3 个表:
Table Room
roomnumber roomtype
1 DeluxeRoom
2 DeluxeRoom
3 DeluxeRoom
100 StandardRoom
101 StandardRoom
102 StandardRoom
Run Code Online (Sandbox Code Playgroud)
Room 是一张存储房间及其类型的表。
Table Reservation
reservationid checkin checkout
1 2017-01-01 2017-01-03
2 2017-01-10 2017-01-20
3 2017-02-05 2017-02-08
Run Code Online (Sandbox Code Playgroud)
预订是用户进行预订的表。
Table RoomReserve
reservationid roomnumber
1 1
2 100
2 101
3 1
3 2
3 3
Run Code Online (Sandbox Code Playgroud)
在 RoomReserve 中,对于每个 bookingid,我可以输入多个 roomnumber 值。如果入住和退房日期不同,我还可以为不同的预订 ID 输入相同的房间号。
当用户想要预订房间时,我试图进行查询来计算可用房间,但我得到的结果是错误的。
这是我正在尝试的代码:
SELECT COUNT(roomnumber)
FROM room
WHERE roomtype='DeluxeRoom'
AND roomnumber NOT IN (
SELECT *
FROM roomreserve r,reservation e, room m
WHERE r.reservation_id=e.reservation_id
AND m.roomnumber=r.roomnumber
AND ('$checkin' BETWEEN start_date AND end_date)
OR ('$checkout' BETWEEN start_date AND end_date)
);
2)
SELECT COUNT(roomnumber)
FROM room
WHERE roomtype='DeluxeRoom'
AND roomnumber NOT IN (
SELECT COUNT(roomnumber)
FROM roomreserve r,reservation e, room m
WHERE r.reservation_id=e.reservation_id
AND m.roomnumber=r.roomnumber
AND ('$checkin' BETWEEN start_date AND end_date)
OR ('$checkout' BETWEEN start_date AND end_date)
);
Run Code Online (Sandbox Code Playgroud)
这是一个比较常见的逻辑错误。
('$checkin' BETWEEN start_date AND end_date) OR
('$checkout' BETWEEN start_date AND end_date));
Run Code Online (Sandbox Code Playgroud)
问题不在于查询的编写方式,而在于您使用了错误的条件。当这两者都不成立时,保留可能会发生冲突,只需在所需值之前开始并在所需值之后结束即可。
您实际上需要找到的是重叠部分。
如果现有预订满足以下条件,则该房间不可用:
任何在您期望的结束时间之前开始并在您期望的开始时间之后结束的预订都属于冲突。
换句话说,在您想要的退房之后入住不可能是冲突,并且在您想要的入住之前退房也不可能是冲突。其他的都是矛盾的。
因此您想要识别这些保留:
(end_date > '$checkin') AND
(start_date < '$checkout');
Run Code Online (Sandbox Code Playgroud)
另请注意,您绝不能像此处所做的那样使用变量插值构建查询。这是一种不安全的做法,没有真正的例外,只有借口。使用准备好的语句和占位符。