¿Te gusta ir al cine? ¿Ha considerado alguna vez cómo es el diseño de la base de datos detrás de su sistema de reservas? En este artículo, prepararemos un modelo de base de datos de ejemplo para una sala de cine.
Hay algunas suposiciones que debemos tener en cuenta:
- las salas de cine múltiplex contemporáneas pueden tener uno o más auditorios dentro de un complejo más grande,
- cada auditorio puede tener un número diferente de asientos,
- los asientos están numerados con el número de fila y la posición del asiento dentro de una fila,
- una película puede tener múltiples proyecciones en diferentes momentos, o puede proyectarse simultáneamente en un auditorio diferente,
- para cada proyección, un asiento se puede reservar/vender solo una vez,
- queremos rastrear quién ingresó cada reserva/venta en el sistema.
Veamos un posible diseño de base de datos para resolver este problema (el modelo se creó con Vertabelo para la base de datos MySQL):
Las descripciones breves de la estructura de la tabla se dan a continuación:
-
La
movieLa tabla contiene datos sobre las películas que se mostrarán en el cine. La clave principal esid, que se incrementa automáticamente como todas las claves principales en todas las demás tablas. El único dato obligatorio estitle.
Todos los campos tienen significados según su nombre. La columna
duration_minpodría usarse para deshabilitar la inserción de una nueva proyección o para mostrar un mensaje de alerta en caso de que queramos ingresar a una proyección en un auditorio donde la proyección anterior aún está en curso:
previous screening start time + duration_min of it > this screening start time -
El
auditoriumtabla identifica todos los auditorios en el teatro. Todos los datos son obligatorios.
Los
seats_noEl campo se puede utilizar para calcular el porcentaje de disponibilidad de auditorios para una proyección/película/auditorio/intervalo de fechas seleccionado. Este es un ejemplo de redundancia de datos porque podríamos obtener el número de asientos para cada auditorio contándolos en elseatmesa. En este ejemplo, es posible que no mejore significativamente el rendimiento. Lo muestro aquí como una idea que podría ayudar a diseñar modelos más complejos. Si configuramos la base de datos de esta manera, debemos tener en cuenta que si cambiamos un dato, también tenemos que cambiar otros. Si añadimos o eliminamos datos delseattabla tenemos que ajustar los valoresseats_noen elauditoriummesa. -
El
screeningLa tabla contiene datos de todas las proyecciones y todos los campos son obligatorios. Una proyección debe tener una película, un auditorio y una hora de inicio relacionados. No podemos tener dos presentaciones en el mismo auditorio al mismo tiempo. Podemos definir una clave única que consta deauditorium_idyscreening_start. Esta configuración es mejor que definir una clave única que consiste enmovie_id,auditorium_idyscreening_startporque eso nos permitiría entrar a las proyecciones de dos películas diferentes al mismo tiempo en el mismo auditorio.
El código de vista previa de Vertabelo SQL para esta tabla se ve así (observe Screening_ak_1):
-- Tables -- Table screening CREATE TABLE screening ( id int NOT NULL AUTO_INCREMENT, movie_id int NOT NULL , auditorium_id int NOT NULL , screening_start timestamp NOT NULL , UNIQUE INDEX Screening_ak_1 (movie_id,auditorium_id,screening_start), CONSTRAINT Screening_pk PRIMARY KEY (id) );
-
El
seatLa tabla contiene una lista de todos los asientos que tenemos en los auditorios con cada asiento asignado estrictamente a un auditorio. Todos los campos son obligatorios.
-
El
reservation_typetable es un diccionario de todo tipo de reservas (por teléfono, online, presencial). Todos los campos son obligatorios.
-
El
employeetabla enumera todos los empleados que utilizan el sistema. Todos los campos son obligatorios.
En los sistemas complejos, generalmente hay más roles, por lo que necesitamos tener un diccionario de roles y una conexión de rol de empleado/usuario. En nuestro ejemplo solo tenemos un rol:la misma persona inserta reservas y vende boletos.
-
La
reservationyseat_reservedLas tablas son las tablas principales de nuestro sistema. Es por eso que los enumeré al final. Todas las demás tablas pueden existir sin tablas de reserva, pero sin las tablas de reserva perderíamos la razón para diseñar toda la base de datos en primer lugar.
La
reservationtabla almacena datos sobre una reserva y/o venta de boletos. Si tenemos una reserva, el atributoreservedse establecería en True, elreservation_type_idse establecería según el origen de la reserva y elemployee_reserved_idcontendría elid_employeevalor de la persona que ingresó los datos (estaría vacío si la reserva se hubiera hecho en línea por parte del cliente). De la misma manera, si se vendieron boletos, elemployee_paid_idse llenaría con elid_employeevalor de la persona que vendió las entradas, el atributo pagado se establecería en True. El atributo activo identifica si un registro sigue siendo válido. Si se vendieran entradas, este atributo siempre sería True y la reserva sin ventas estaría activa hasta 30 min antes de que comience la proyección
El
seat_reservedmesa nos permite hacer una reserva o un pago para varios asientos. Después de que el empleado verifique algunos asientos libres en la interfaz, se agregará un registro a esta tabla para cada uno de ellos. Si queremos comprobar qué asientos están libres o ocupados podemos consultar los valores en esta tabla unida a lareservationtabla dondereservation.active = True.
Cabe mencionar:
employee_reserved_idno es obligatorio porque puede no existir una reserva para un asiento (se vende un boleto para un asiento sin reserva previa) o se hace en líneareservation_type_ides una clave externa que hace referencia al "id" del tipo de reserva. No es obligatorio porque puede no existir reserva (en caso de que realicemos una venta sin reserva previa)reservation_contactes un campo de entrada de texto para almacenar datos de una persona que realizó una reserva, no es obligatorio porque una reserva podría no existir (en caso de que realicemos una venta sin reserva previa)employee_paid_idestá relacionado con un usuario que realizó una venta, no es obligatorio porque es posible que no se haya producido una venta (el asiento se reservó, la reserva se canceló automáticamente, el asiento no se vendió)paides una bandera que indica que el pago se ha realizado y es obligatorio (los valores pueden ser Sí/Verdadero o No/Falso)
Al final, ten en cuenta que a nadie le gusta encontrar a alguien más en su asiento: