2012-01-18 10 views
7

Sto scrivendo un sistema di prenotazione hotel. dopo un sacco di studio (tra cui overflow dello stack) Ho scritto questo sql per scoprire camere libere:Verifica dei conflitti dell'intervallo di date in MySQL

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

ma il problema è la sua, non considerando il controllo il tempo è 12:00:00 e checkout è 11:59:00

anche se non fornisce le query corrette come all'interno dell'intervallo di date non funziona come se io prenotassi da 15-18 una stanza singola il cui numero è 501. se eseguo ancora una query 17-19 questa stanza sembra gratis ma in la realtà dovrebbe essere occupata.

chiunque può suggerire un sql molto buono ed efficace che otterrà la data precisa in modo che nessuno scontro accadrà il sistema di prenotazione perché il sistema verrà implementato in modo reale, quindi gli errori causeranno molti problemi.

grazie in anticipo

risposta

23

Il problema che stai avendo è che la query non è sufficientemente robusto. Quando si abbattere il problema, quello che hai è questo:

Se l'intervallo definito da $check_in e $check_out si sovrappone al range definito dalla checkin e checkout in alcun modo, allora la stanza viene ammonito dall'arbitro. Altrimenti, è gratuito.

Questo significa che:

  • Se $check_in> = checkin e $check_in < = checkout, la camera è PRENOTATA
  • O Se $check_out> = checkin e $check_out < = checkout, la camera è PRENOTATO
  • O Se $check_in < = checkin e $check_out> = checkout, la stanza è PRENOTATO

Quindi, è necessario rappresentare entrambi questi scenari nel vostro subquery al fine di ottenere le informazioni che sei cercando.

Inoltre, si spera che si utilizzi datetime per i propri confronti e non solo time, altrimenti si avranno effetti collaterali.

EDIT: query SQL

(Tenete a mente che v'è più di un modo per scuoiare un gatto, per così dire sto solo fornendo un esempio che continua con quello che hai già tanto. il più possibileAncora una volta, sto anche supponendo che checkin, checkout, $check_in e $check_out saranno tutti a risolvere datetime tipi)

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

Ciao grazie per la tua risposta. puoi per favore scrivere un simulatore sql in modo che io possa seguire perché non sono molto bravo a scrivere sql (mysql precisamente) grazie ancora –

+3

questa è una buona presa! Quella query controlla entrambe le estremità dell'intervallo, ma che dire del mezzo? In altre parole, supponiamo che il cliente stia cercando di prenotare una stanza per 4 notti, ma era già prenotato per una notte nel mezzo? Il check-in della prenotazione sarebbe superiore al check-in $ richiesto e il checkout della prenotazione sarebbe inferiore al check-out $ richiesto, ma la stanza non è disponibile .... giusto? – Aerik

+0

@Aerik Questa è una bella ripresa - aggiornerò la mia risposta di conseguenza. –

1

Penso che questo potrebbe iniziare nella giusta direzione ...

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

La logica originaria era molto vicino, hai solo bisogno di scambiare i valori '$check_in' e '$check_out'. Cioè .:

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

risposta di Brian Driscoll si concentra sugli scenari che costituiscono prenotazione conflitti, come così:

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

Tuttavia le senarios che costituiscono non conflitto sono molto più semplici. Ci sono solo due:

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

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

Quindi la situazione in cui non v'è alcun conflitto tra una prenotazione e un potenziale di prenotazione può essere espresso con questo SQL:

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

Per controllare i conflitti, invece, abbiamo solo bisogno per negare questo. Quindi, usando la legge di DeMorgans, la negazione è:

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

... che arriva alla soluzione di cui sopra.

+0

Buona risposta ............ –

Problemi correlati