Vous êtes sur la page 1sur 5

Correction TD1

Exercice 2

Le sujet de cet exercice est l'oeuvre de Cécile CAPPONI, tout comme la majorité de cette correction.
Certaines questions vous ont été épargnées dans l'énoncé du TD, vous les trouverez toutefois
dans cette correction.

Pour la plupart des questions, il peut exister plusieurs solutions algébriques (puisque certains
opérateurs s'expriment en fonction d'autres). Nous donnons ici une solution pour chaque question,
et parfois deux solutions pour montrer des différences importantes.

Pour bien comprendre les requêtes que vous jugez difficiles, un bon moyen est de spécifier, à
chaque étape de l'expression algébrique, les relations mises en jeu (avec leurs attributs).

1) Lister les noms d'hôtels et leur ville


Il s'agit ici d'une simple projection, puisque toutes les informations sont présentes dans la
relation hotel, et puisqu'il n'y a aucune restriction.

*) Combien y-a-t-il de clients enregistrés ?


L'attribut numclient est unique dans la relation client : il suffit donc d'en compter les occurrences
(aucun groupement n'est nécessaire).

RESULTAT = AGREGAT(client ; ; COUNT(numclient))

2) Lister les noms d'hôtels ayant 3 étoiles ou plus.


On commence par restreindre les tuples d'hôtels ayant strictement plus de 2 étoiles, et on
projette sur le nom des hôtels retenus.

R1 = RESTRICT(hotel, etoiles > 2)


RESULTAT = PROJECT(R1, nom)

*) Lister les clients dont le nom commence par 'H' (la fonction START(string, char) renvoie TRUE si la
chaîne string commence par le caractère char).

On applique une restriction sur le nom des clients, en appliquant à chaque nom une fonction pour
vérifier la condition de restriction.

RESULTAT = RESTRICT(client, START(nom, 'H'))

3) Lister les hôtels sur lesquels portent une réservation.

On réalise une semi-jointure entre les relations hotel et reservation, puisque c'est la relation reservation
qui compile les réservations effectuées, et que c'est la relation hotel qui détient les attributs que l'on
veut “en sortie" (en projection). Ceci est équivalent à une jointure naturelle suivie d'une projection
sur les attributs de hotel.

RESULTAT = NATURAL SEMI-JOIN(hotel, reservation)

*) Lister les clients ayant déjà occupé (ou en cours d'occupation d') une chambre.

RESULTAT = NATURAL SEMI-JOIN(client, occupation)

4) Lister les clients n'ayant pas occupé (ou pas en cours d'occupation d') une chambre.
Soit R1 le résultat la question précédente. Il suffit ici de considérer tous les clients de la base, et
d'enlever ceux qui ont déjà occupé une chambre : il reste alors ceux qui n'en ont jamais occupé.

RESULTAT = MINUS(client, R1)

5) Pour chaque hôtel, indiquer le nombre total de chambres

On groupe le résultat de la jointure entre hotel et chambre par hôtel (numéro, nom et ville). On obtient
alors, pour chaque hôtel, l'ensemble des chambres qui y sont : il suffit alors de compter le nombre
de numchambre, unique à l'intérieur de chaque hôtel.

R1 = NATURAL JOIN(hotel, chambre)


RESULTAT = AGREGAT(R1 ; R1.numhotel, R1.nom, R1.ville ; COUNT(R1.numchambre) )

*) Pour chaque hôtel, quel est le prix moyen de ses chambres ? Le prix maximum ? Le prix
minimum ?

On retrouve pour cette question la relation R1 de la question 9 ; mais la fonction d'agrégat diffère,
et s'applique non pas sur le numéro de la chambre, mais sur le prix de la chambre.

R1 = NATURAL JOIN(hotel, chambre)


RESULTAT = AGREGAT(R1 ; R1.numhotel, R1.nom, R1.ville ; AVG(R1.prixnuitht) )

Pour avoir le minimum (resp. le maximum) du prix, on remplace la fonction de calcul de l'agrégat
par MIN (resp. MAX).

6) Quels sont tous ceux qui ont été, ou sont encore, clients de l'hôtel des voyageurs à Nice ?

Pour la première question, il s'agit de repérer les clients dont le numéro est référencé dans une
occupation de chambre d'un hôtel précis. Pour cela, on commence par ne garder que l'hôtel en
question (son numéro suffit: R2) puis on doit faire le lien entre cet hôtel et les occupations qui le
concerne (R3), et à partir de là, on peut faire une jointure pour mettre en relation chaque client
avec la chambre occupée.

R1 = RESTRICT(hotel, nom = 'Hotel des voyageurs' AND ville = 'Nice')


R2 = PROJECT (R1.numhotel)
R3 = NATURAL JOIN(R1, occupation)
R4 = JOIN(client, R3, client.numclient = R3.numclient)
RESULTAT = PROJECT(R4, numclient, nom, prenom)

7) Combien de chambres triples possède l'Hôtel des ambassadeurs à Grenoble ?

R1 = RESTRICT( hotel, nom = 'Hotel des ambassadeurs' AND ville = 'Grenoble')


R2 = RESTRICT( chambre, type = 'triple')
R3 = JOIN(R1, R2, R1.numhotel = R2.numhotel)
RESULTAT = AGREGAT( R3 ; ; COUNT(R3.numchambre) )

Remarquons que la relation R3 est obtenue par jointure : il s'agit plus exactement d'une jointure
naturelle puisque le seul attribut qu'ont en commun R1 et R2 est numhotel. dans ce cas, il est
préférable de spécifier directement (en algèbre relationnelle) cette jointure naturelle, pour un
soucis de lisibilité. Il est donc préférable d'écrire :
R3 = NATURAL JOIN(R1, R2)

*) Combien y-a-t-il d'hôtels enregistrés à Bordeaux ?

On groupe selon chaque hôtel restreint à Bordeaux, et on compte dans chaque groupe, le nombre
de numéros d'hôtel trouvés dans ce groupe.
R1 = RESTRICT(hotel, ville = 'Bordeaux')
RESULTAT = AGREGAT(R1 ;; COUNT(numhotel) )

*) Pour chaque chambre de chaque hôtel, compter le nombre de clients y ayant séjourné, ou y
séjournant encore.

On groupe par chambre d'hôtel, on récupère les clients de chaque groupe par jointure, et on
compte le numéro de client dans chaque groupe (un groupe étant une chambre).

R1 = NATURAL JOIN(hotel, chambre)


R2 = NATURAL JOIN(client, occupation)
R3 = PROJECT(R2, numclient, numhotel, numchambre)
R4 = JOIN(R1, R3, R1.numhotel = R3.numhotel)
RESULTAT = AGREGAT( R4 ; nom, ville, numchambre ; COUNT(numclient) )

8) Pour chaque client, lister le nom des hôtels dans lesquels il a séjourné, ou séjourne encore,
avec les dates d'arrivée et de départ correspondant à chaque séjour.

Il faut ici faire attention aux jointures naturelles car deux attributs ont le même identificateur mais
n'ont rien à voir : le nom de l'hôtel et le nom du client. Pour lever l'ambiguïté, nous précisons d'où
vient l'attribut en le préfixant par une variable liée à la table correspondante. Dans la requête SQL,
lever cette ambiguïté est plus aisé, puisque nous devons renommer les tables intermédiaires qui
sont arguments de jointure.

R1 = NATURAL JOIN(occupation, client C)


R2 = JOIN( R1, hotel H, R1.numhotel = H.numhotel)
-- ici deux colonnes de même nom existent, d'où les renommages : C.nom et H.nom
RESULTAT = PROJECT(R2, C.nom, prenom, H.nom, ville, datearrivee, datedepart)

*) Existe-t-il plusieurs hôtels portant le même nom, et si oui, lesquels ?

On doit faire une jointure entre deux exemplaires de la même relation.

R1 = JOIN(hotel H1, hotel H2, H1.nom = H2.nom)


R2 = RESTRICT(R1, H1.numhotel <> H2.numhotel)
RESULTAT = PROJECT(R2, H1.nom, H1.ville, H2.ville)

Ici, nous ne faisons pas une jointure naturelle, puisque les deux relations de la jointure ont les
mêmes attributs : on spécifie donc la condition de jointure (sur le nom de l'hôtel).

9) Lister les numéros de chambres disponibles dans l'hôtel de la gare, à Bordeaux, pour les nuits
du 12 avril 2014 au 17 avril 2014 .

Nous devons ici répertorier les chambres qui ne sont ni occupées ni réservées pendant une
période considérée. On répertorie donc toutes les chambres occupées -- ou réservées -- pendant
cette période, et on retire ces dernières de la liste de toutes les chambres de l'hôtel de la base de
données.
-- ci-dessous, on se restreint à l'hôtel de la gare de Bordeaux
R1 = RESTRICT( hotel, nom = 'Hotel de la gare' AND ville = 'Bordeaux' )
-- ci-dessous, on répertorie toutes les occupations de cet hôtel
R2 = NATURAL JOIN( R1, occupation)
-- ci-dessous, on répertorie toutes les réservations de cet hôtel
R'2 = NATURAL JOIN( R1, reservation)
-- ci-dessous, on sélectionne toutes les occupations de l'hôtel pendant la période considérée
R3 = RESTRICT ( R2, (17/04/2014 >= datedepart > 12/04/2014) OR (17/04/2014 > datearrivee >= 12/04/2014)
OR ( datearrivee <= 12/04/2014 AND (datedepart >= 17/04/2014 OR datedepart IS NULL ) ) )
R'3 = PROJECT (R3, numhotel, numchambre)
-- ci-dessous, on sélectionne toutes les réservations de l'hôtel pendant la période considérée
R4 = RESTRICT ( R'2, (17/04/2014 >= datedepart > 12/04/2014) OR (17/04/2014 > datearrivee >= 12/04/2014)
OR ( datearrivee <= 12/04/2014 AND (datedepart >= 17/04/2014 OR datedepart IS NULL ) ) )
R'4 = PROJECT (R4, numhotel, numchambre)
-- ci dessous, on fait de l'union de touotes les chambres occupées ou réservées pendant la période
R5 = UNION(R'3, R'4) -- on s'assure que les schémas de R'3 et R'4 sont identiques
-- ci-dessous, on garde toutes les chambres de l'hôtel sans critère de date
R6 = NATURAL JOIN( R1, chambre )
R'6 = PROJECT ( R6, numhotel, numchambre )
-- ci-dessous, on retire de toutes les occupations et résa celles qui sont pendant la période considérée
R7 = MINUS (R'6, R5) -- on s'assure que les schémas de R'6 et R5 sont identiques
-- On projette sur le numéro de la chambre
RESULTAT = PROJECT( R7, numchambre )

10) Si la TVA est de 19.6%, quel sera le montant de chaque séjour que le client Jean Némarre a
eu à régler à la date du 02/04/2014 (on ne compte donc pas un éventuel séjour actuel non
terminé) ?

Il faut répertorier les séjour du client précisé. Nous commençons par repérer le client en question
(dans R1). puis nous passons par la relation occupation pour récupérer toutes les chambres que ce
client a occupées avant le 02/04/2014 (R2 puis R3), et nous passons enfin par la relation chambre
pour obtenir le prix de la chambre occupée dans le séjour concerné (jointure R4), et enfin nous
projetons le résultat obtenu par hôtel, chambre, client, dates d'arrivée et de départ (tout cela
constitue un "séjour"), et nous faisons un calcul sur ces attributs pour calculer le montant de la
facture TTC (le prix des chambres est HT).

R1 = PROJECT ( RESTRICT(client, nom='Némarre' AND prenom = 'Jean'), numclient )


R2 = NATURAL JOIN ( R1, occupation )
R3 = RESTRICT ( R2, datedepart IS NOT NULL AND datedepart <= 02/04/2014 )
R4 = NATURAL JOIN ( R3, chambre )
RESULTAT = PROJECT (R4, R4.numhotel, R4.numchambre, R4.numclient,
R4.datearrivee, R4.datedepart,
(R4.prixnuitht + R4.prixnuitht*0,196)*(R4.datedepart-R4.datearrivee))

11) Quelles sont les chambres (hôtel et numéro) qui ont été occupées plus de 40 jours ? Quels
sont les clients qui ont occupé toutes ces chambres ?

Il suffit de compter, pour chaque chambre jointe avec les occupations de cette chambre, le nombre
de jours d'occupation en sommant sur la différence départ-arrivée de chaque séjour. On ne garde
alors que ces chambres dont le nombre de jours calculés en R2 dépasse 40.

R1 = PROJECT ( occupation, numchambre, numhotel, (datedepart - datearrivee) nbj )


R2 = AGREGAT( R1 ; numchambre, numhotel ; SUM(nbj) totaljours )
RESULTAT = RESTRICT( R2, totaljours >=40 )

Pour la seconde question, il suffit de réaliser une jointure entre le résultat de la requête précédente
et les clients, via les occupations enregistrées. On utilise ainsi deux fois la même relation
occupation, mais pour des objectifs différents (pour repérer les chambres très utilisées d'une part, et,
ensuite, pour repérer les clients qui ont séjourné dans ces chambres, même pour une très courte
durée.
R1 = PROJECT ( occupation, numchambre, numhotel, (datedepart - datearrivee) nbj )
R2 = AGREGAT( R1 ; numchambre, numhotel, numclient ; SUM(nbj) totaljours )
R3 = RESTRICT( R2, totaljours >=40 )
R4 = NATURAL JOIN( client, occupation)
R5 = NATURAL JOIN(R4, R3)
RESULTAT = PROJECT(R5, numclient, nom, prenom)
*) Quels sont les clients (nom et prénom) qui ont toujours séjourné au premier étage ?

Pour répondre à ce type de question où apparaît un « toujours » (et donc, un « jamais » sur une
condition opposée), l'opérateur de différence est le plus pratique (comme dans la question 8) : on
répond à la question « quels sont les clients qui ont occupé une chambre ailleurs qu'au premier
étage », et on enlève ceux-là de la liste de tous les clients ayant déjà occupé une chambre.

R1 = NATURAL JOIN (client, occupation)


R2 = RESTRICT (chambre, etage <> 1)
R3 = NATURAL JOIN (R1, R2)
R4 = PROJECT (R3, numclient, nom, prenom)
R5 = PROJECT (R1, numclient, nom, prenom)
RESULTAT = MINUS( R5, R4 )

Vous aimerez peut-être aussi