[Plantemiento] BD de reservas de un hotel

Iniciado por dimitrix, 14 Enero 2010, 00:28 AM

0 Miembros y 1 Visitante están viendo este tema.

dimitrix

Pue eso, no se muy bien cual sería la forma para plantear el siguiente problema:

Tenemos el hotel "Pepito Grillo", este hotel tiene 10 habitaciones, 5 normales, 2 super y 3 ultrasupers.
El gerente quiere que se pueda reservar con hasta 6 meses de antelación.
-------------------

Pues ¿Como se podría plantear?, por que vale, hacer que mire si un día queda una habitación libre vale, pero mirar si una habitación se encuentra ocupada durante 7 días. Entonces, tendría que haber un una tabla que guarde como registros cada habitación o como lo podría plantear?

Aunque parezca ejercicio de clase es más bien para aprender por ahora el planteamiento y hacerlo.

Un saludo y mil gracias.




^Tifa^

Hola.

Lo mas que se me ocurre a estas horas de la noche  :xD  son 4 tablas.
3 para cada juego de habitacion (Ultra, Normal, Super) y 1 tabla 'padre' que se encarga de mostrar los dias, fecha, y habitaciones elegidas a permanecer y salir. Me explico (Aunque este ejemplo obvie la tabla Super... pero te vale el ejemplo solo es agregar la tabla Super):

Código (sql) [Seleccionar]


mysql> describe Normal;
+---------------+------------+------+-----+---------+-------+
| Field         | Type       | Null | Key | Default | Extra |
+---------------+------------+------+-----+---------+-------+
| codigo_normal | char(2)    | YES  | MUL | NULL    |       |
| inicial       | date       | YES  |     | NULL    |       |
| final         | date       | YES  |     | NULL    |       |
| id            | tinyint(4) | YES  |     | NULL    |       |
+---------------+------------+------+-----+---------+-------+
4 rows in set (0.00 sec)

mysql> describe Ultra;
+--------------+------------+------+-----+---------+-------+
| Field        | Type       | Null | Key | Default | Extra |
+--------------+------------+------+-----+---------+-------+
| codigo_ultra | char(3)    | YES  | MUL | NULL    |       |
| inicial      | date       | YES  |     | NULL    |       |
| final        | date       | YES  |     | NULL    |       |
| id           | tinyint(4) | YES  |     | NULL    |       |
+--------------+------------+------+-----+---------+-------+
4 rows in set (0.00 sec)

mysql> describe Reservaciones;
+---------+------------+------+-----+---------+-------+
| Field   | Type       | Null | Key | Default | Extra |
+---------+------------+------+-----+---------+-------+
| codigo  | char(3)    | YES  |     | NULL    |       |
| entrada | date       | YES  |     | NULL    |       |
| dias    | tinyint(4) | YES  |     | NULL    |       |
| faltan  | tinyint(4) | YES  |     | NULL    |       |
| id      | tinyint(4) | YES  |     | NULL    |       |
+---------+------------+------+-----+---------+-------+
5 rows in set (0.00 sec)



Hay que hacer una relacion de las entidades si decides no usar motor InnoDB con FK. Si decides usar Myisam tendrias que crear TRIGGERS para mantener actualizada la data entre la tabla hijo-padre... bien (Tambien deberas indicar cuales son los indices porke los he obviado para el ejemplo... tengo un poco de suenio )

Ahora observa la data en mis tablas:

Código (sql) [Seleccionar]


mysql> select * from Reservaciones;
+--------+------------+------+--------+------+
| codigo | entrada    | dias | faltan | id   |
+--------+------------+------+--------+------+
| A1     | 2010-01-07 |  -12 |     -6 |    1 |
| A1     | 2010-03-20 |   -5 |    -71 |    2 |
| A2     | 2010-07-20 |   -8 |   -128 |    3 |
| B2     | 2010-09-20 |   -7 |   -128 |    1 |
| B1     | 2010-05-20 |  -10 |   -128 |    2 |
| B2     | 2010-02-14 |   -6 |    -38 |    3 |
+--------+------------+------+--------+------+
6 rows in set (0.00 sec)                     

mysql> select * from Ultra;
+--------------+------------+------------+------+
| codigo_ultra | inicial    | final      | id   |
+--------------+------------+------------+------+
| B2           | 2010-09-20 | 2010-09-27 |    1 |
| B1           | 2010-05-20 | 2010-05-30 |    2 |
| B2           | 2010-02-14 | 2010-02-20 |    3 |
+--------------+------------+------------+------+
3 rows in set (0.00 sec)                         

mysql> select * from Normal;
+---------------+------------+------------+------+
| codigo_normal | inicial    | final      | id   |
+---------------+------------+------------+------+
| A1            | 2010-01-07 | 2010-01-19 |    1 |
| A1            | 2010-03-20 | 2010-03-25 |    2 |
| A2            | 2010-07-20 | 2010-07-28 |    3 |
+---------------+------------+------------+------+
3 rows in set (0.00 sec)



Ya que para reducir un poco la redundancia, califique las habitaciones por codigo  :D habitacion Normal = A1,A2,A3, etc... habitacion Ultra = B1, B2, B3, etc... y podrias crear tu otra tabla de habitaciones Super con C1, C2, C3 como codigo de referencia  ;)  asi sabras diferenciar en la tabla padre de que habitaciones se esta hablando.

Ahora te preguntaras como yo, inroduje en la tabla padre 'Reservaciones' los dias a durar hospedado alguien en un hotel, o cuantos dias le faltan a partir de la fecha actual para ingresar al hotel (En este ultimo campo 'faltan' deberas actualizarlo diariamente, ya que cada dia que pasa le queda 1 menos para que se hospede el visitante). Todo lo hice con una consulta SQL extremadamente pesada para el motor... (Estoy un poco vaga para hacer TRIGGERS) Pero aqui te va un ejemplo.

* Primero inserto datos en la tabla Normal o Ultra
* Luego hago:

Código (sql) [Seleccionar]

mysql> insert into Reservaciones values('B2','2010-02-14',(select datediff(inicial,final) from Ultra where id = 3),(select datediff(current_date,final) from Ultra where id = 3), 3);


Espero que se capte mas o menos la idea... es un mero ejemplo, obviamente podria desglosarse hasta en 5 tablas distinta las relaciones... pero yo las reduje en 4 (3 tablas habitaciones , 1 tabla padre)


dimitrix

WoW ^TiFa^, sorprendente, muchas gracias, lo que pasa es que no puedo estar todos los días actualizando la base de datos, pero ya sabría hacer eso automático :P

Entonces la única pega que tengo es lo de las relaciones, a ver, yo nunca hice relaciones (excepto en access), uso PHP+SQL y veo el resultado en PhpMyadmin, pero relaciones te refieres como en access? Es que nunca hice eso...

Yo, para reservar, si me dice:
Habitación normal, del día 1, al día 15, pues miraría en la tabla "Reservaciones" la primera habitación si está libre entre esas fechas(mirando si está libre, el día, 1, el día 2, el día 3...), sino, pasaría a la siguiente, así escaneando todas hasta encontrar alguna libre.

No se, comentame...




^Tifa^

Hola.

Siento mucho no haberme expandido en lo antes explicado, realmente tenia mucho suenio  :-\ cuando postee esto.

Pero te sirve de guia.

CitarWoW ^TiFa^, sorprendente, muchas gracias, lo que pasa es que no puedo estar todos los días actualizando la base de datos, pero ya sabría hacer eso automático :P

Lo positivo de las bases de datos relacionales (Al menos las que yo conozco) tienen disponible internamente un CRON  ::) con esto puedes crearte una tarea programada cada 24 horas que se ejecute 1 sola vez, asi mantendras actualizadas de forma automatica el campo 'faltan' para cada fecha ya reservada. Si usas un motor sin esta capacidad, tendrias que dar uso del Sistema Operativo y programar una tarea (un script) que se conecte cada 24 horas a la DB una sola vez y actualize dicho campo 'faltan'.

CitarEntonces la única pega que tengo es lo de las relaciones, a ver, yo nunca hice relaciones (excepto en access), uso PHP+SQL y veo el resultado en PhpMyadmin, pero relaciones te refieres como en access? Es que nunca hice eso...

Ahhhh... no se como relaciona access los asuntos  :-\  aqui tendrias que explicarme.

CitarYo, para reservar, si me dice:
Habitación normal, del día 1, al día 15, pues miraría en la tabla "Reservaciones" la primera habitación si está libre entre esas fechas(mirando si está libre, el día, 1, el día 2, el día 3...), sino, pasaría a la siguiente, así escaneando todas hasta encontrar alguna libre.

Pues suponiendo que quieres ver que habitaciones no estan reservadas desde la fecha '2010-01-07' a la fecha '2010-03-20' (Basandome en el ejemplo de las tablas que postee anteriormente) Seria algo como:

SELECT * FROM Reservaciones WHERE entrada NOT BETWEEN '2010-01-07' AND '2010-03-20'

No lo he probado... pero seria mas o menos algo asi, asi te retornaria todas las habitaciones que NO tienen reservaciones desde el dia 07 de Enero hasta el dia 20 de Enero del 2010. Sino te retorna nada, esto indica que desde el 07 de Enero al 20 de Enero no hay ninguna reservacion hecha, por lo que tienes libres todos esos dias en cualquier habitacion para poder reservar.

dimitrix

Lo de las relaciones no te preocupes:

CitarSELECT * FROM Reservaciones WHERE entrada NOT BETWEEN '2010-01-07' AND '2010-03-20'

Pero con esto, solo miraría si el día 7 de enero y 3 de marzo está reservado, pero... y si da la casualidad que alguien reserva del 6 de enero al 8 de enero y del 18 de marzo al 25 de marzo?




Tifa, antes que nada eres persona, me hiciste una respuesta super cojonuda, vales un huevo, ni te preocupes :P




^Tifa^

CitarCitar
SELECT * FROM Reservaciones WHERE entrada NOT BETWEEN '2010-01-07' AND '2010-03-20'

Pero con esto, solo miraría si el día 7 de enero y 3 de marzo está reservado, pero... y si da la casualidad que alguien reserva del 6 de enero al 8 de enero y del 18 de marzo al 25 de marzo?

Las evaluaciones BETWEEN indican un rango total o sea, si tu dices:

NOT BETWEEN '2010-01-03' AND '2010-01-20'

Esta condicion dice, que te retornara todos los registros que NO esten dentro de la fecha desde '2010-01-03' hasta '2010-01-20' Se evalua completo.. desde .. hasta. Ahora si en su lugar quieres saber cuales SI estan reservadas dentro de la fecha desde el dia 03 de Enero al 20 de Enero (Esto incluye todas las habitaciones reservadas a partir del dia 03,04,05,06,07...etc hasta el dia 20 de Enero) utilizarias entonces:

SELECT * FROM table WHERE entrada BETWEEN '2010-01-03' AND '2010-01-20'

En vez de NOT BETWEEN usas BETWEEN.

Si al contrario tu unicamente quieres conocer que habitaciones estan reservadas el dia 03 y dia 07 de Enero solamente esos 2 dias no los dias que estan entre ellos dos, usarias:

SELECT * FROM tabla WHERE entrada IN('2010-01-03','2010-01-07')

Ahora si tu quieres saber que habitaciones estan reservadas desde el dia 03 de Enero al 15 de Enero y desde el dia 5 de Marzo al 25 de Marzo.

SELECT * FROM tabla WHERE entrada BETWEEN '2010-01-03' AND '2010-01-15' AND '2010-03-05' AND '2010-01-25'

Ahora si tu solamente quieres saber las fechas de Reservacion de un cliente en especifico, ahi tu table Reservaciones debera crecer jejejejeje agregandole el campo cliente con su respectivo ID.

dimitrix

Jajaja muchas gracias, es que me parecía raro que BETWEEN pudiera ver "entre dos fechas", sabiendo cuantos días tiene el mes, y si es año bisiesto o no.

MUCHAS GRACIAS!




^Tifa^

Al inicio puede parecer un poco complicado o no entendible... pero veras que es sencillo  ;) con el tiempo.

Yo misma aveces cuando son consultas SQL con numeros que debo realizar me enredo  :rolleyes: aunque termine haciendola, y llevo una especie de iguala con algunos amigos que programan en PHP donde vivo y ellos mismos aveces no dan con el objetivo de enlazar varias entidades entre 4 o 5 tablas a la vez y me piden ayuda o alguna referencia de como pueden hacerlo.

Ya sabes que por mi parte a tus ordenes si tienes mas preguntas  ;) en relacion a esto de SQL.