2012-01-18 37 views
7

Estoy escribiendo un sistema de reserva de hotel. después de mucho estudio (incluyendo desbordamiento de pila) Escribí este SQL para averiguar habitaciones libres:Comprobación de conflictos de rango de fechas en MySQL

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

pero el problema es que no está teniendo en cuenta el tiempo de comprobación es 12:00:00 y la salida es 11:59:00

también no está dando las consultas correctas, como dentro del rango de fechas, no funciona como si reservo de 15-18 una habitación individual cuyo número es 501. si nuevamente ejecuto una consulta 17-19, esta habitación parece libre pero en la realidad debería estar ocupada.

alguien puede sugerir un sql muy bueno y eficaz que obtendrá la fecha exacta para que no se produzca ningún choque sistema de reserva porque el sistema se implementará en realidad por lo que los errores causarán muchos problemas.

gracias de antemano

Respuesta

23

El problema que tiene es que su consulta no es lo suficientemente robusto. Cuando usted analiza el problema, lo que se tiene es la siguiente:

Si el rango definido por $check_in y $check_out se solapa con el intervalo definido por checkin y checkout en cualquier manera, entonces la habitación está reservada. De lo contrario, es gratis.

Esto significa que:

  • Si $check_in> = checkin y $check_in < = checkout, la habitación es RESERVADO
  • O Si $check_out> = checkin y $check_out < = checkout, la habitación es RESERVADO
  • O Si $check_in < = checkin y $check_out> = checkout, la habitación es RESERVADO

Por lo tanto, es necesario para representar estos dos escenarios en su sub consulta con el fin de obtener la información que está buscando.

Además, con suerte utilizará datetime para sus comparaciones y no solo time, de lo contrario, tendrá efectos secundarios.

EDIT: consultas SQL

(Tenga en cuenta que hay más de una manera de pelar un gato, por así decirlo Sólo estoy proporcionando un ejemplo que guarda con lo que ya tiene la mayor cantidad. como sea posible.Una vez más, también estoy asumiendo que checkin, checkout, $check_in y $check_out serán todos a resolver datetime tipos)

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

hola gracias por su respuesta. puede escribir un simulacro sql para que pueda seguir porque no soy muy bueno en la escritura de sql (mysql precisamente) gracias de nuevo –

+3

¡eso es un buen truco! Esa consulta verifica ambos extremos del rango, pero ¿qué hay del medio? En otras palabras, supongamos que el cliente estaba tratando de reservar una habitación por 4 noches, ¿pero ya estaba reservado para una noche en el medio? El registro de la reserva sería superior al $ check_in solicitado y el registro de la reserva sería inferior al $ check_out solicitado, pero la habitación no está disponible ... ¿no? – Aerik

+0

@ Aerik Eso es una buena sorpresa para ti mismo. Actualizaré mi respuesta en consecuencia. –

1

Creo que esto podría empezar en la dirección correcta ...

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

Su lógica original estaba muy cerca, sólo tiene que cambiar los valores '$check_in' y '$check_out'. Es decir .:

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

respuesta de Brian Driscoll se centra en los escenarios que constituyen reserva de conflictos, así como:

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

Sin embargo los senarios que constituyen ningún conflicto son mucho más simples. sólo dos están:

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

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

Así que la situación en la que no hay conflicto entre una reserva y una reserva potencial se puede expresar con este SQL:

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

para comprobar si hay conflictos en cambio, sólo tenemos para negar esto. Entonces, usando la Ley DeMorgans, la negación es:

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

... que llega a la solución anterior.

+0

Buena respuesta ............ –

Cuestiones relacionadas