[英]Checking for date range conflicts in MySQL
我正在寫一個酒店預訂系統。 經過大量研究(包括堆棧溢出),我編寫了此sql來找出免費房間:
SELECT
*
FROM room
WHERE
room_id NOT IN (
SELECT room_id
FROM bookings
WHERE
checkin <= '$check_in'
AND checkout >= '$check_out'
)
但問題是它沒有考慮時間檢查是12:00:00和結帳是11:59:00
同樣,它沒有像日期范圍內那樣提供正確的查詢,也無法正常工作,就像我從15-18預訂一個單人房,房間的編號是501。如果我再次運行查詢17-19,這個房間似乎是免費的,但實際上應該是占據。
任何人都可以建議一個很好且有效的sql來獲取准確的日期,這樣就不會發生預訂系統沖突,因為該系統將在實際中實施,因此錯誤會導致很多問題。
提前致謝
您遇到的問題是您的查詢不夠可靠。 當您解決問題時,您所擁有的是:
如果$check_in
和$check_out
定義的范圍以任何方式與checkin
和checkout
定義的范圍重疊,則將預訂房間。 否則,它是免費的。
這意味着:
$check_in
> = checkin
和$check_in
<= checkout
,客房已預訂 $check_out
> = checkin
和$check_out
<= checkout
,客房已預訂 $check_in
<= checkin
和$check_out
> = checkout
,客房已預訂 因此,您需要在子查詢中代表這兩種情況,以獲得所需的信息。
另外,希望您將使用datetime
進行比較,而不僅僅是time
,否則會產生副作用。
編輯:SQL查詢
(請記住,可以說有多種方法可以給貓剝皮。我只是提供一個示例,盡可能地保留您已有的貓。我再次假設checkin
, checkout
, $check_in
和$check_out
將全部解析為datetime
類型)
SELECT *
FROM room
WHERE room_id NOT IN
(SELECT room_id
FROM bookings
WHERE
(checkin <= '$check_in' AND checkout >= '$check_in') OR
(checkin <= '$check_out' AND checkout >= '$check_out') OR
(checkin >= '$check_in' AND checkout <= '$check_out'))
您的原始邏輯非常接近,您只需要交換'$check_in'
和'$check_out'
值即可。 即:
SELECT *
FROM room
WHERE room_id NOT IN
(
SELECT room_id
FROM bookings
WHERE checkin <= '$check_out' AND checkout >= '$check_in'
)
Brian Driscoll的答案側重於構成預訂沖突的方案,因此:
---------------|-----Booked-----|---------------
|----A1----|
|----A2----|
|--A3--|
|----------A4----------|
Case A2 & A3: checkin <= '$check_in' AND checkout >= '$check_in'
Case A1 & A3: checkin <= '$check_out' AND checkout >= '$check_out'
Case A4: checkin >= '$check_in' AND checkout <= '$check_out'
然而,構成不沖突的senarios要簡單得多。 只有兩個:
---------------|-----Booked-----|---------------
|----B1----|
|----B2----|
Case B1: checkin > '$check_out'
Case B2: checkout < '$check_in'
因此,可以使用以下SQL表示預訂和潛在預訂之間沒有沖突的情況:
checkin > '$check_out' OR checkout < '$check_in'
要檢查沖突,我們只需要對此進行否定即可。 因此,使用德摩根定律,求反是:
checkin <= '$check_out' AND checkout >= '$check_in'
...得出上面給出的解決方案。
我認為這可能會讓您朝正確的方向開始...
SELECT R.*
FROM room AS R
LEFT OUTER JOIN bookings AS B USING (room_id)
WHERE B.room_id IS NULL
OR (B.checkout < '$check_in'
AND B.checkin > '$check_out')
這里有一些好主意: http : //forums.digitalpoint.com/showthread.php?t=63746
另外,您要使用哪種列類型來進行簽入和簽出? 您確定要在$ check_in和$ check_out中傳遞正確格式的值嗎?
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.