Fonctions de date/heure en MySQL


précédentsommairesuivant

Réservation d'une chambre d'hotel

Enoncé du problème
Un hotel contient des chambres. Ces chambres sont réservées pour une période plus ou moins longue. On ne peut réserver une chambre si quelqu'un a déjà réservé la chambre sur la même période. En fonction de la période désirée, on veut afficher les chambres disponibles.

Ce problème s'applique à tous types de réservations (salles, matériel, formateurs...).



Pour représenter ce problème, on dispose des tables suivantes :

  • Chambre : les chambres
  • Réservation : les réservations, avec numéro de chambre, id du client, date de début, de fin
  • Client : les clients de l'hotel
Script de création
Sélectionnez
CREATE TABLE chambre (
  numero INT PRIMARY KEY AUTO_INCREMENT,
) ;


CREATE TABLE client (
  id  INT PRIMARY KEY AUTO_INCREMENT,
  nom CHAR(30) NOT NULL
) ;


CREATE TABLE reservation (
  numeroChambre INT  NOT NULL,
  idClient      INT  NOT NULL,
  dateDebut     DATE NOT NULL,
  dateFin       DATE NOT NULL,
  
  PRIMARY KEY(numeroChambre, idClient, dateDebut),
  CONSTRAINT FOREIGN KEY fk_numeroChambre (numeroChambre) REFERENCES chambre(numero),
  CONSTRAINT FOREIGN KEY fk_idClient      (idClient)      REFERENCES client(id)
)



Insertion des données
Sélectionnez
INSERT INTO chambre
VALUES
(1),
(2),
(3) ;

INSERT INTO client
VALUES
(1, "pcaboche"),
(2, "Maximillian"),
(3, "Debug") ;


INSERT INTO reservation
(1, 1, "2006-07-03", "2006-07-16"),
(1, 2, "2006-07-17", "2006-07-30"),
(2, 3, "2006-07-10", "2006-07-23") ;

La requête

Pour ce problème, on dispose de 2 variables: $debut et $fin (il s'agit de variables issues de l'application préparant la requête, ici une application PHP). Ces variables représentent respectivement les dates de début et de fin de la periode pour laquelle on souhaite effectuer une réservation.

Bien entendu, il faut que l'on ait la relation $debut < $fin pour que la requête marche. Cette vérification doit être effectuées dans le programme appelant la requête.

Pour que la réservation soit possible, il faut que les intervalles [$debut, $fin] et [reservation.dateDebut, reservation.dateFin] ne se chevauchent pas.

Pour cela, on part de l'ensemble des chambres, duquel on enlève les chambres pour lesquelles on a au moins une réservation durant la période considérée. Comme en MySQL on ne dispose pas de l'opérateur EXCEPT (ou MINUS), on fait cela avec une jointure LEFT OUTER JOIN et un test IS NULL.

Voici donc au final la requête :

 
Sélectionnez
SELECT chambre.*

FROM chambre

LEFT OUTER JOIN reservation
ON (
  chambre.numero = reservation.numeroChambre

  AND (
      $debut BETWEEN reservation.dateDebut AND reservation.dateFin
   OR $fin   BETWEEN reservation.dateDebut AND reservation.dateFin
   OR reservation.dateDebut BETWEEN $debut AND $fin
   OR reservation.dateFin   BETWEEN $debut AND $fin
  )
)

WHERE reservation.numeroChambre IS NULL

Cette requête retournera la liste des chambres libres sur la période considérée.


précédentsommairesuivant

Vous avez aimé ce tutoriel ? Alors partagez-le en cliquant sur les boutons suivants : Viadeo Twitter Facebook Share on Google+   

  

Copyright © 2006 Pierre Caboche. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.