這是查詢的工作原理,並已經過任何其他職位空缺組合的測試。任何事情之後空缺。在現有開始之前,之後開始日期。結束日期在現有結束日期之前,之後。完全跨在另一個預訂之外。完全在另一個預訂。
select
r.RoomID
from
Room r
LEFT JOIN
(select
b.RoomID
from
booking b,
(select @parmStartDate := '2016-01-21',
@parmEndDate := '2016-01-23' ) sqlvars
where
b.EndDate >= @parmStartDate
AND b.StartDate <= @parmEndDate
AND ( timestampdiff(day, b.StartDate, @parmEndDate)
* timestampdiff(day, @parmStartDate, b.EndDate )) > 0) Occupied
ON r.RoomID = Occupied.RoomID
where
Occupied.RoomID IS NULL;
樣品預訂數據創建我包括
BookID RoomID StartDate EndDate
1 1 2016-02-03 2016-02-04
2 1 2016-02-04 2016-02-08
3 1 2016-02-12 2016-02-16
4 1 2016-02-20 2016-02-28
然後我用下面的預訂日期檢測,符合下列有效空缺VS衝突,並已經被佔用了上來。此測試僅適用於單人房間,但顯然適用於酒店的任何房間。
Both dates before anything on file... Room available
2016-01-10 - 2016-01-15
Both dates after anything on file... Room available
2016-03-10 - 2016-03-15
Occupied ID 1 -- Same start date
2016-02-03 - 2016-02-04
Occupied ID 2 -- Same start date, but less than existing occupied end date
2016-02-04 - 2016-02-05
Occupied ID 2 -- Same start, Exceeds end occupancy date
2016-02-04 - 2016-02-09
Occupied ID 3 -- Start before, but end date WITHIN existing booking
2016-02-09 - 2016-02-13
Available. The END Date is the START Date of the existing booking
(Between 2 & 3 booking)
2016-02-09 - 2016-02-12
Occupied ID 3 -- Started within date, but end outside existing booking
2016-02-15 - 2016-02-17
Available. End of existing booking and nothing booked on 2/17
2016-02-16 - 2016-02-17
Occupied ID 3 -- Completely encompasses booking entry
2016-02-11 - 2016-02-17
Occupied ID 4 -- totally WITHIN another entry
2016-02-21 - 2016-02-23
現在來解釋發生了什麼。我使用了LEFT-JOIN並尋找NULL(即:與另一個預訂不衝突),這與您的NOT IN子查詢非常相似。所以我會跳過那部分。
首先是FROM子句。所以我不必像存儲過程那樣「聲明」變量,我正在通過@parmStartDate,@parmEndDate進行IN-LINE操作,併爲了聲明目的分配別名sqlvars。由於這返回一行,所以將笛卡爾應用於預訂表是沒有問題的。
from
booking b,
(select @parmStartDate := '2016-01-21',
@parmEndDate := '2016-01-23' ) sqlvars
現在,WHERE子句。如果你的表有多年價值的預約時間後,客房的100的,這有可能會相當大快,所以我想只有那些日期在那裏現有的訂單會來到位這預啓動是
where
b.EndDate >= @parmStartDate
AND b.StartDate <= @parmEndDate
至少,我只關心那些現有結帳日期至少是您嘗試查找空房時間的預訂。例如:您正在尋找7月4日的入住日期。爲什麼你會關心是否有人在2月,3月,4月等等退房?所以現在,你走多遠......你也只關心那些下一個現有預訂有開始日期最多的記錄您將要退房的那一天。所以,如果7月6日檢查,你不關心7月7日或之後的任何預訂。到現在爲止還挺好。
現在,我來了解如何知道房間是否被佔用。我在比較現有的開始日期和查找日期方面遇到了困難,並且得到了錯誤的答案,所以我不得不求助於日期數學,並將開始時間和結束時間以及結束時間進行比較以開始,如果乘數結果爲正數,則會出現衝突。
AND ( timestampdiff(day, b.StartDate, @parmEndDate)
* timestampdiff(day, @parmStartDate, b.EndDate )) > 0)
既然我們已經知道,我們有可能的日期範圍內的記錄,這是在做任一方向衝突檢查全外面,裏面,衝突向左或向右衝突。它只是工作。
你將不得不看到它更好地理解它,這是我跑的查詢,所以你可以看看你自己的結果。只需插入您正在查找的相應開始/結束日期即可。
select
b.BookID,
b.RoomID,
b.StartDate,
b.EndDate,
@parmStartDate as pStart,
@parmEndDate as pEnd,
( timestampdiff(day, b.StartDate, @parmEndDate)
* timestampdiff(day, @parmStartDate, b.EndDate )) <= 0 as Available,
( timestampdiff(day, b.StartDate, @parmEndDate)
* timestampdiff(day, @parmStartDate, b.EndDate )) > 0 as Occupied
from
booking b,
(select @parmStartDate := '2016-01-21',
@parmEndDate := '2016-01-23' ) sqlvars
好運...
如果事件A在事件B結束之前開始並且在事件B開始之後結束,則事件A與事件B重疊。 – Strawberry
@Strawberry像這樣,其中'3-8-2016'選擇開始和'3-15-2016'選擇結束? 'SELECT * FROM b WHERE 3-8-2016 <= startDate AND endDate <='3-15-2016'OR'3-8-2016'> = startDate AND endDate> ='3-15-2016'OR'3 -816'> = startDate AND endDate <='3-15-2016'AND(startDate> = NOW()AND endDate> = NOW())OR'3-8-2016'<= startDate AND endDate> = '3-15-2016'和((''3-8-2016'在startDate和endDate之間)或('3-15-2016'在startDate和endDate之間))' – rel1x
編號重新閱讀我的評論。 – Strawberry