Sie sind auf Seite 1von 3

Buenas a todos,

Estoy enganchado con una consulta SQL que me lleva algun que otro quebradero de cabeza.
Atendiendo a lo que se pide aqui: http://forums.mysql.com/read.php?10,302739,302739#msg-
302739 os comento:

Intento hacer un sistema de reservas de hostal interno para dnde estoy trabajando (El
sistema trabajara en PHP/MySQL, pero ahora solo me interesa la consulta SQL). Lo que me
gustaria es que dada una fecha de entrada y una fecha de salida, me devuelva la primera
habitacion que se puede alquilar (o si quitamos el LIMIT 1; del final, pues el listado de
habitaciones alquilables).

Resultado de obtener SELECT Version();:

5.1.41-3ubuntu12.3
La version es la que se puede obtener instalando Ubuntu Server 10.04.1 desde los
repositorios (sudo apt-get install mysql-server mysql-client)

La base de datos se llama 'gestion'.

Tabla de habitaciones:

CREATE TABLE IF NOT EXISTS `habitaciones` (


`id` int(11) NOT NULL AUTO_INCREMENT,
`personas` tinyint(1) NOT NULL,
`piso` tinyint(1) NOT NULL,
`comentarios` longtext NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;

Contenido de habitaciones(Recortado):

INSERT INTO `habitaciones` (`id`, `personas`, `piso`, `comentarios`)


VALUES
(1, 2, 1, ''),
(2, 1, 1, ''),
(3, 3, 1, ''),
(4, 2, 1, ''),
(5, 2, 1, ''),
(6, 2, 1, ''),
(7, 3, 1, ''),
(8, 3, 1, ''),
(9, 3, 1, '');

Tabla de reservas:

CREATE TABLE IF NOT EXISTS `reservas` (


`id` int(11) NOT NULL AUTO_INCREMENT,
`entrada` date NOT NULL,
`salida` date NOT NULL,
`idCliente` int(11) NOT NULL,
`idHabitacion` int(11) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
El contenido de la tabla de Reservas est vacio, ahora por ahora. Tambien hay una tabla de
clientes, pero no sera necesarea, insertaremos siempre el idCliente = 1.

Os explicare lo que he ido haciendo. Primera consulta SQL que he construido para obtener la
primera habitacin libre:

SELECT h.id FROM habitaciones h WHERE id NOT IN ( SELECT idHabitacion


FROM reservas r WHERE r.entrada >= '2010-07-05' AND r.salida <= '2010-
07-10' ) LIMIT 1;
Me devuelve el ID 1. Vale, Insertamos la reserva:

INSERT INTO `gestion`.`reservas` (`id`, `entrada`, `salida`,


`idCliente`, `idHabitacion`) VALUES (NULL, '2010-07-05', '2010-07-10',
'1', '1');
Ahora si volvemos a ejecutar la consulta de arriba, nos devuelve la habitacion '2'.

Cambiaremos la consulta para que la fecha de entrada sea 2010-07-11 y fecha de salida
2010-07-15...

SELECT h.id FROM habitaciones h WHERE id NOT IN ( SELECT idHabitacion


FROM reservas r WHERE r.entrada >= '2010-07-11' AND r.salida <= '2010-
07-15' ) LIMIT 1;
Nos re-devuelve la habitacion 1, es correcto. La reservamos:

INSERT INTO `gestion`.`reservas` (`id`, `entrada`, `salida`,


`idCliente`, `idHabitacion`) VALUES (NULL, '2010-07-11', '2010-07-15',
'1', '1');

Ahora vamos a comprobar la primera habitacion libre para entrar el da '2010-07-03' y salir el
da '2010-07-18'..

SELECT h.id FROM habitaciones h WHERE id NOT IN ( SELECT idHabitacion


FROM reservas r WHERE r.entrada >= '2010-07-03' AND r.salida <= '2010-
07-18' ) LIMIT 1;
Nos ha devuelto la 2, la reservamos tambien

INSERT INTO `gestion`.`reservas` (`id`, `entrada`, `salida`,


`idCliente`, `idHabitacion`) VALUES (NULL, '2010-07-03', '2010-07-18',
'1', '2');

Ahora toca comprobar la disponibilidad para entrar da '2010-07-01' y salir el '2010-07-06'.

SELECT h.id FROM habitaciones h WHERE id NOT IN ( SELECT idHabitacion


FROM reservas r WHERE r.entrada >= '2010-07-01' AND r.salida <= '2010-
07-06' ) LIMIT 1;
Nos devuelve la 2... y si miramos en la tabla reservas, la dos ya esta reservada, a entrar el dia
'2010-07-03', se acaban de solapar.

Aqui es donde empieza mi quebradero de cabeza, y la consulta cambia pasando


por(ejemplo):

SELECT h.id FROM habitaciones h WHERE h.id NOT IN (


SELECT DISTINCT r.idHabitacion FROM reservas r
WHERE (r.entrada <= '2010-07-01' AND r.salida >= '2010-07-06') OR
(r.entrada >= '2010-07-01' AND r.salida <= '2010-07-06') ) LIMIT 1;
Que aqui aun se solapava alguna habitacion.

La consulta ahora la tengo asi, como fecha de entrada '2010-07-10' y fecha de salida '2010-
07-11', que si os acordais, la habitacion 1 esta libre esa noche... y me devuelve la 3:

SELECT h.id FROM habitaciones h WHERE h.id NOT IN (


SELECT r.idHabitacion FROM reservas r WHERE (
( r.entrada BETWEEN '2010-07-10' AND '2010-07-11' ) OR ( r.salida
BETWEEN 2010-07-10' AND '2010-07-11' )
OR ( r.entrada <= '2010-07-10' AND r.salida >= '2010-07-11' ) )
) LIMIT 1;
Con esta consulta no se me solapan reservas, lo unico que se pierden noches, y no creo que
esto sea bueno a la larga. Igual que si pongo fecha de entrada '2010-07-01' y salida '2010-07-
05' me devuelve la 3, y si fecha de salida es '2010-07-04' me devuelve la 1.

La pregunta del milln: Como deberia acabar de adaptar la 'SELECT' para que no me solape
reservas y pueda reservar la ID=1 la noche del 10 al 11, y me de la ID=1 cuando entre dia 1 y
salga dia 5?

Gracias de antemano, y si les falta informacin, pidanla sin temor ;P

Das könnte Ihnen auch gefallen