2015-01-16 33 views
0

我有以下表結構SQL進行房間可用性

客房

||| room_id ||| name ||| 
||| 1 ||| best ||| 
||| 2 ||| best ||| 
||| 3 ||| best ||| 
||| 4 ||| best ||| 

預訂

||| room_id ||| date_start ||| date_end  ||| 
||| 1 ||| 2015-01-10 ||| 2015-01-15 ||| 
||| 2 ||| 2015-01-10 ||| 2015-01-18 ||| 
||| 3 ||| 2015-01-05 ||| 2015-01-10 ||| 
||| 4 ||| 2015-01-02 ||| 2015-01-05 ||| 

我想是讓說,如果用戶搜索date_start = 2015-01-10date_end = 2015-01-14

我想顯示那些日子的空房間。

這是我到目前爲止已經試過

SELECT r.* 
FROM rooms r 
WHERE r.room_id NOT IN (
    SELECT b.room_id FROM bookings b 
    WHERE (b.date_start <= '$data[datestart]' AND b.date_end >= '$data[dateend]')) 

謝謝!

+0

你能分享一下你試過的嗎? –

+0

MySQL支持OVERLAPS嗎? – jarlh

+0

@jayBlanchard我加了 – jlocker

回答

1

看的可能性:

x/y = your query's "find available for these days" 
a/b = various records' start/end in your db 

這裏的每一種可能的變體:

a b 
---+----+--- 
xy | |  // no overlap 
x | y |  // partial overlap 
x | | y // complete overlap 
    | xy |  // complete overlap 
    | x | y // partial overlap 
    | | xy // no overlap 

一旦緊縮的邏輯下,你最終

(y < a) || (x > b) // no overlap at all 
+0

這是一種有趣的思維方式,這是一種已知的方法(如果是,它叫做什麼?),還是僅僅是你分析OP問題的方法?謝謝 – joe

+0

如果你允許在同一天的下午辦理登機手續,那麼它會是'(y <= a) || (x > = b)' – Sean

+0

@joe:它基本上只是布爾代數。爲重疊圖的每一行寫出一個表達式,將所有表達式放在一起,然後減少它們。 –

0
SELECT rooms.room_id, rooms.name FROM rooms 
INNER JOIN bookings 
ON rooms.room_id =bookings.room_id 
WHERE bookings.date_start >= DATE('2015-01-10') AND bookings.date_end <= DATE('2015-01-14'); 
+0

如果某人從01-11到01-12預訂了房間,該怎麼辦?該房間將不可用,但由您的查詢返回。 – AdamMc331

+0

是真的,這就像檢查兩個日期之間的預訂,而不是可用的房間。 – joe

+0

嘿,對不起,我沒有考慮它。我正在考慮提供的具體問題。 謝謝 – squiroid

1

如果你正在考慮這樣一個日期範圍小號01/10和01/14,有三種情況,其中一個房間不可用:

  • 有人有一個起始日期01/10和01/14
  • 之間必須有人01/10之間的結束日期和01/14
  • 有人在01/10之前的開始日期和01/14之後的結束日期。

因此,對於前兩個,您可以使用BETWEEN運算符來查看日期是否落在該範圍內,並且其他人是否使用大於或小於。

我有什麼建議,是編寫一個查詢來獲取可用客房:

SELECT r.* 
FROM room r 
JOIN bookings b ON b.room_id = r.room_id 
WHERE b.date_start BETWEEN '2015-01-10' AND '2015-01-14' 
    OR b.date_end BETWEEN '2015-01-10' AND '2015-01-14' 
    OR (b.date_start < '2015-01-10' AND b.date_end > '2015-01-14'); 

然後你就可以使用NOT IN從rooms_table的房間不在此禁止列表中選擇:

SELECT r.* 
FROM room r 
WHERE r.room_id NOT IN(
    SELECT r.room_id 
    FROM room r 
    JOIN bookings b ON b.room_id = r.room_id 
    WHERE b.date_start BETWEEN '2015-01-10' AND '2015-01-14' 
    OR b.date_end BETWEEN '2015-01-10' AND '2015-01-14' 
    OR (b.date_start < '2015-01-10' AND b.date_end > '2015-01-14')); 

如果你想避免的子查詢,你可以否定你的每一個條件得到可用客房:

SELECT r.* 
FROM room r 
JOIN bookings b ON b.room_id = r.room_id 
WHERE b.date_start NOT BETWEEN '2015-01-10' AND '2015-01-14' 
    AND b.date_end NOT BETWEEN '2015-01-10' AND '2015-01-14' 
    AND (b.date_start >= '2015-01-10' OR b.date_end <= '2015-01-14'); 

這裏是所有三個例子的SQL Fiddle

+0

嗨謝謝!..但我有一個小問題,我所有的預訂信息都在另一個單獨的表格中,如(客戶名稱,電子郵件)..如何從該表中選擇所有表單? – jlocker

+0

您可以在與預訂表和客戶表相關的列上包含另一個加入。 – AdamMc331

+0

它涉及到使用booking_id,請告訴我在哪裏可以包括它?..謝謝 – jlocker