2012-01-18 25 views
7

Piszę system rezerwacji hoteli. Po wielu studiuje (w tym przepełnienie stosu) Napisałem to sql, aby dowiedzieć się wolne pokoje:Sprawdzanie konfliktów zakresu dat w MySQL

SELECT 
* 
FROM room 
WHERE 
    room_id NOT IN (
     SELECT room_id 
     FROM bookings 
     WHERE 
       checkin <= '$check_in' 
      AND checkout >= '$check_out' 
    ) 

ale problemem jest to jej nie rozważa sprawdzanie czas 12:00:00 i kasa jest 11:59:00

również nie podaje właściwych zapytań, np. W zakresie dat nie działa tak, jakbym zarezerwował od 15-18 jednoosobowy pokój, którego numer to 501. jeśli ponownie uruchomię zapytanie 17-19, to pokoje wydają się darmowe, ale w rzeczywistość powinna być zajęta.

każdy może zaproponować bardzo dobry i skuteczny sql, który otrzyma dokładną datę, aby nie doszło do zderzenia systemu rezerwacyjnego, ponieważ system zostanie wdrożony w rzeczywistości, więc błędy spowodują wiele problemów.

góry dzięki

Odpowiedz

23

Problem masz to, że zapytanie nie jest wystarczająco wytrzymałe. Po rozbić ten problem, co masz to:

Jeżeli zakres zdefiniowany przez $check_in i $check_out pokrywa zakres wyznaczany przez checkin i checkout w dowolnym sposób, to pokój jest zarezerwowany. W przeciwnym razie jest za darmo.

oznacza to, że:

  • Jeśli $check_in> = checkin i $check_in < = checkout, pokój jest ZAREZERWOWANY
  • lub Jeśli $check_out> = checkin i $check_out < = checkout, pokój to ZAREZERWOWANY
  • LUB Jeśli $check_in < = checkin i $check_out> = checkout, pokój jest ZAREZERWOWANY

Tak, trzeba do reprezentowania obu tych scenariuszy w podzapytania w celu uzyskania informacji jesteś szukam.

Ponadto, będziesz mieć nadzieję, że do porównań użyjesz datetime, a nie tylko time, w przeciwnym razie będziesz mieć efekty uboczne.

EDIT: Zapytanie SQL

(Należy pamiętać, że istnieje więcej niż jeden sposób na skórę kota, że ​​tak powiem ja tylko zapewnienie przykład, który utrzymuje się z tego, co już masz tyle. jak to możliwe.Po raz kolejny, ja również przy założeniu, że checkin, checkout, $check_in i $check_out będzie wszystko rozwiązać do datetime typów)

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')) 
+0

Cześć, dziękuję za odpowiedź. Czy możesz napisać makiety sql, dzięki czemu mogę śledzić, bo nie jestem zbyt dobry w pisaniu sql (mysql dokładnie) dzięki jeszcze raz –

+3

to dobry połów! To zapytanie sprawdza oba końce zakresu, ale co z środkowym? Innymi słowy, załóżmy, że klient próbował zarezerwować pokój na 4 noce, ale został już zarezerwowany na jedną noc w środku? Rezerwacja checkin byłaby większa niż żądana check_in $, a rezerwacja checkout byłaby mniejsza niż żądanie check_out $, ale pokój jest niedostępny .... prawda? – Aerik

+0

@Aerik To dobry chwyt - zaktualizuję odpowiedź odpowiednio. –

1

myślę, że to może Ci zacząć w dobrym kierunku ...

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') 
10

Oryginalna logika była bardzo blisko, wystarczy zamienić wartości '$check_in' i '$check_out'. Tj .:

SELECT * 
FROM room 
WHERE room_id NOT IN 
(
    SELECT room_id 
    FROM bookings 
    WHERE checkin <= '$check_out' AND checkout >= '$check_in' 
) 

odpowiedź Brian Driscolla skupia się na scenariuszach, które stanowią konflikty rezerwacji, a więc:

---------------|-----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' 

Jednak senarios stanowiące nie konfliktu są znacznie prostsze. Istnieją tylko dwa:

---------------|-----Booked-----|--------------- 
    |----B1----|        
            |----B2----| 

Case B1: checkin > '$check_out' 
Case B2: checkout < '$check_in' 

więc sytuacja, w której nie ma konfliktu między rezerwacji i ewentualnej rezerwacji może być wyrażona z tym SQL:

checkin > '$check_out' OR checkout < '$check_in' 

aby sprawdzić konflikty zamiast tego wystarczy zaprzeczać temu. Tak więc, stosując DeMorgans prawa, negacja jest:

checkin <= '$check_out' AND checkout >= '$check_in' 

... który przybywa do rozwiązania podanego powyżej.

+0

Dobra odpowiedź ............ –