L'algèbre relationnelle et ses arbres
Ce que ce chapitre apporte 5 points
- Expliquer pourquoi le moteur a besoin d'une algèbre entre la requête SQL et son exécution.
- Employer les opérations de base, et prévoir ce que chacune fait aux lignes et aux colonnes.
- Composer plusieurs opérations et lire l'arbre qui en résulte.
- Traduire une question en français ou une requête SQL en expression algébrique, et l'inverse.
- Réécrire un arbre en un arbre équivalent moins coûteux, et chiffrer ce qu'il épargne.
Une école range ses inscriptions dans une base, une agence ses clients, ses projets et les heures de ses employés. La scolarité veut le nom des étudiants de la classe 1A ; la direction, les employés affectés à tous les projets d'un client. Une requête SQL dit ce qu'on veut, jamais comment l'obtenir : c'est le moteur qui choisit la marche à suivre, et il raisonne dans l'algèbre relationnelle. Ses opérations, sélection, projection, jointure, division, prennent des tables et rendent une table, et l'arbre algébrique les met en ordre. Ce chapitre part des tables construites au chapitre Du MCD au modèle relationnel. Il fait lire ces arbres nœud par nœud, puis écrire des expressions que la page vérifie. Savoir les lire, c'est comprendre pourquoi deux requêtes qui donnent le même résultat ne coûtent pas le même prix.
Pourquoi une algèbre
SQL est un langage déclaratif. Une requête décrit le résultat voulu et ne dit rien de la marche à suivre. Le moteur, lui, doit bien choisir une marche à suivre, et il en existe des dizaines pour une même requête. Il lui faut donc un langage intermédiaire : assez formel pour être manipulé mécaniquement, assez proche des données pour que chaque opération soit exécutable. C'est l'algèbre relationnelle.
Ce chapitre vient avant celui des requêtes SQL, et ses figures sont pourtant accompagnées de leur traduction en SQL. Elle se lit sans connaître le langage : SELECT nom FROM Employe WHERE salaire > 2000 se dit presque comme la phrase française, « le nom des employés dont le salaire dépasse 2000 ». Le chapitre sur les requêtes SQL enseigne chacun de ces mots-clés.
Cette algèbre repose sur une seule idée, et tout le reste en découle.
La propriété de clôture. Chaque opération prend une ou deux relations et rend une relation. Le résultat d'une opération est donc lui-même un opérande valide pour la suivante.
C'est ce qui permet d'emboîter les opérations sans limite, et c'est pourquoi une requête se dessine en arbre. Les feuilles sont les tables de la base, chaque nœud une opération, la racine le résultat final.
Un mot de vocabulaire, parce qu'il revient partout. Une relation est un ensemble de lignes ayant les mêmes attributs. Le mot ensemble n'est pas décoratif : en algèbre relationnelle, une relation ne contient pas deux fois la même ligne. SQL, lui, tolère les doublons, ce qui explique le mot-clé DISTINCT. Cette différence produit une surprise à la projection, on y revient plus bas.
La base de démonstration
Presque toutes les figures de ce chapitre travaillent sur la base employée par les chapitres SQL : la même table Employe répond σ_{salaire > 2000}(Employe) ici, et répondrait SELECT * FROM Employe WHERE salaire > 2000 dans un bloc SQL, avec les mêmes lignes. Quelques figures déclarent leurs propres petites tables, deux listes de noms ou six affectations à des projets, pour isoler une opération ; elles le disent.
Cliquer sur un nœud pour voir la relation qu'il produit.
| idEmploye | nom | prenom | salaire | date_embauche | service |
|---|---|---|---|---|---|
| 1 | Girard | Nadia | 2450 | 2019-04-01 | Etudes |
| 2 | Lemoine | Paul | 1980 | 2021-09-15 | Support |
| 3 | Barbier | Sofia | 3100 | 2016-01-10 | Etudes |
| 4 | Roche | Tom | 2200 | 2022-03-07 | Support |
| 5 | Vidal | Lucie | 2750 | 2018-11-23 | Commerce |
La base compte neuf relations, en deux parties. Côté université : des classes, des étudiants, des enseignants, des cours, et les inscriptions des étudiants aux cours avec leur note. Côté entreprise : des clients, leurs projets, des employés, et les heures que chacun passe sur chaque projet.
| Relation | Attributs | Lignes |
|---|---|---|
Classe | idClasse, nomClasse, annee | 3 |
Etudiant | idEtudiant, nom, prenom, dateNaissance, email, ville, idClasse, actif | 10 |
Enseignant | idEnseignant, nomEns, prenomEns, specialite | 3 |
Cours | idCours, intitule, volumeHoraire, coefficient, idEnseignant | 7 |
Inscription | idEtudiant, idCours, note | 25 |
Client | idClient, nom, prenom, ville | 4 |
Projet | idProjet, libelle, idClient | 4 |
Employe | idEmploye, nom, prenom, salaire, date_embauche, service | 5 |
TravailleSur | idEmploye, idProjet, heures | 7 |
La partie université prolonge l'exemple du chapitre Du MCD au modèle relationnel, avec une table Classe et quelques attributs de plus. Dans Enseignant, le nom et le prénom s'appellent nomEns et prenomEns : après une jointure avec Etudiant, deux colonnes nom ne se distingueraient plus. Deux cours n'ont pas d'enseignant et deux inscriptions n'ont pas encore de note : la valeur absente s'écrit NULL, et elle servira plus bas.
Afficher le contenu des neuf tables
Classe
| idClasse | nomClasse | annee |
|---|---|---|
| 1 | 1A | 1 |
| 2 | 1B | 1 |
| 3 | 2A | 2 |
Etudiant
| idEtudiant | nom | prenom | dateNaissance | ville | idClasse | actif | |
|---|---|---|---|---|---|---|---|
| 1 | Martin | Lea | 2004-03-12 | lea.martin@ecole.fr | Paris | 1 | 1 |
| 2 | Diallo | Amine | 2003-11-02 | amine.diallo@ecole.fr | Lyon | 1 | 1 |
| 3 | Dupond | Sophie | 2004-07-25 | sophie.dupond@ecole.fr | Paris | 1 | 1 |
| 4 | Durand | Tom | 2003-05-30 | tom.durand@ecole.fr | Nantes | 2 | 0 |
| 5 | Lefebvre | Ines | 2004-01-18 | ines.lefebvre@ecole.fr | Lyon | 2 | 1 |
| 6 | Bernard | Yanis | 2002-09-08 | NULL | Paris | 2 | 1 |
| 7 | Moreau | Chi | 2004-02-14 | chi.moreau@ecole.fr | Paris | 3 | 1 |
| 8 | Marchand | Hugo | 2003-08-21 | NULL | Bordeaux | 3 | 1 |
| 9 | Nguyen | Elsa | 2004-11-30 | elsa.nguyen@ecole.fr | Lyon | 3 | 1 |
| 10 | Petit | Sofia | 2002-12-05 | sofia.petit@ecole.fr | Nantes | 1 | 0 |
Enseignant
| idEnseignant | nomEns | prenomEns | specialite |
|---|---|---|---|
| 1 | Durand | Claire | Bases de donnees |
| 2 | Ferrand | Marc | Algorithmique |
| 3 | Aubert | Sophie | Statistiques |
Cours
| idCours | intitule | volumeHoraire | coefficient | idEnseignant |
|---|---|---|---|---|
| 1 | Bases de donnees | 30 | 2.0 | 1 |
| 2 | Algorithmique | 24 | 1.5 | 2 |
| 3 | Mathematiques | 36 | 2.5 | 3 |
| 4 | Physique | 27 | 2.0 | NULL |
| 5 | Informatique | 30 | 2.0 | 1 |
| 6 | Statistiques | 18 | 1.0 | 3 |
| 7 | Reseaux | 21 | 1.5 | NULL |
Inscription
| idEtudiant | idCours | note |
|---|---|---|
| 1 | 1 | 15.5 |
| 1 | 3 | 17.0 |
| 1 | 5 | 13.0 |
| 2 | 1 | 8.5 |
| 2 | 3 | 14.0 |
| 2 | 4 | 11.5 |
| 3 | 1 | 11.0 |
| 3 | 2 | 16.5 |
| 3 | 3 | 19.0 |
| 3 | 7 | 9.5 |
| 4 | 2 | NULL |
| 4 | 4 | 7.0 |
| 5 | 1 | 18.0 |
| 5 | 6 | 13.5 |
| 5 | 7 | 12.0 |
| 6 | 3 | 6.0 |
| 6 | 4 | 10.0 |
| 7 | 2 | 14.5 |
| 7 | 5 | 15.0 |
| 8 | 1 | 12.5 |
| 8 | 6 | NULL |
| 9 | 3 | 16.0 |
| 9 | 4 | 17.5 |
| 9 | 5 | 9.0 |
| 10 | 2 | 10.5 |
Client
| idClient | nom | prenom | ville |
|---|---|---|---|
| 1 | Durand | Paul | Paris |
| 2 | Leroy | Sarah | Lyon |
| 3 | Moreau | Karim | Paris |
| 4 | Fontaine | Eva | Bordeaux |
Projet
| idProjet | libelle | idClient |
|---|---|---|
| 1 | Portail client | 1 |
| 2 | Refonte ERP | 2 |
| 3 | Application mobile | 3 |
| 4 | Audit reseau | 4 |
Employe
| idEmploye | nom | prenom | salaire | date_embauche | service |
|---|---|---|---|---|---|
| 1 | Girard | Nadia | 2450 | 2019-04-01 | Etudes |
| 2 | Lemoine | Paul | 1980 | 2021-09-15 | Support |
| 3 | Barbier | Sofia | 3100 | 2016-01-10 | Etudes |
| 4 | Roche | Tom | 2200 | 2022-03-07 | Support |
| 5 | Vidal | Lucie | 2750 | 2018-11-23 | Commerce |
TravailleSur
| idEmploye | idProjet | heures |
|---|---|---|
| 1 | 1 | 120 |
| 1 | 3 | 40 |
| 2 | 1 | 80 |
| 3 | 2 | 200 |
| 3 | 3 | 60 |
| 4 | 4 | 35 |
| 5 | 2 | 90 |
Dans les figures, chaque feuille d'un arbre se clique aussi, et affiche sa table.
Les opérations de base
Sélection (σ)
La sélection garde certaines lignes et ne touche pas aux colonnes. La condition s'écrit en indice, entre accolades. σ_{salaire > 2000}(Employe) se lit à voix haute : « les employés dont le salaire dépasse 2000 ».
Cliquer sur un nœud pour voir la relation qu'il produit.
| idEmploye | nom | prenom | salaire | date_embauche | service |
|---|---|---|---|---|---|
| 1 | Girard | Nadia | 2450 | 2019-04-01 | Etudes |
| 3 | Barbier | Sofia | 3100 | 2016-01-10 | Etudes |
| 4 | Roche | Tom | 2200 | 2022-03-07 | Support |
| 5 | Vidal | Lucie | 2750 | 2018-11-23 | Commerce |
Les conditions se combinent avec ∧ (et), ∨ (ou), ¬ (non). Les opérateurs de comparaison sont =, ≠, <, >, ≤, ≥.
Cliquer sur un nœud pour voir la relation qu'il produit.
| idEmploye | nom | prenom | salaire | date_embauche | service |
|---|---|---|---|---|---|
| 1 | Girard | Nadia | 2450 | 2019-04-01 | Etudes |
Une comparaison dont un des membres vaut NULL n'est jamais vraie : ni note = NULL, ni note ≠ NULL, ni note > 10. Elle n'est pas fausse non plus : elle est inconnue, et la négation d'une inconnue reste inconnue. Une sélection ne garde que les lignes où la condition est vraie. Une note absente est donc écartée par σ_{note > 10}, et aussi par σ_{¬(note > 10)}.
Elle peut en revanche rester quand une autre partie de la condition suffit. Avec ∨, un seul côté vrai rend le tout vrai : σ_{note > 10 ∨ idCours = 2}(Inscription) garde l'inscription sans note de l'étudiant 4 au cours 2.
L'algèbre d'origine ne connaît pas NULL. C'est SQL qui l'ajoute, avec cette logique à trois valeurs (vrai, faux, inconnu), et qui réserve une écriture à part pour le tester, IS NULL.
Cliquer sur un nœud pour voir la relation qu'il produit.
| idEtudiant | idCours | note |
|---|---|---|
| 2 | 1 | 8.5 |
| 3 | 7 | 9.5 |
| 4 | 4 | 7 |
| 6 | 3 | 6 |
| 6 | 4 | 10 |
| 9 | 5 | 9 |
Modifier l'expression, puis « Recalculer » : l'arbre se redessine sur les mêmes tables.
Projection (π)
La projection garde certaines colonnes et ne filtre aucune ligne. Du moins en apparence. π_{nom, salaire}(Employe) se lit : « le nom et le salaire de chaque employé ».
Cliquer sur un nœud pour voir la relation qu'il produit.
| nom | salaire |
|---|---|
| Girard | 2450 |
| Lemoine | 1980 |
| Barbier | 3100 |
| Roche | 2200 |
| Vidal | 2750 |
Voici la surprise annoncée plus haut. Une relation est un ensemble : elle ne peut pas contenir deux fois la même ligne. Si la projection fait disparaître ce qui distinguait deux lignes, celles-ci se confondent et le résultat en compte une seule.
Cliquer sur un nœud pour voir la relation qu'il produit.
| service |
|---|
| Etudes |
| Support |
| Commerce |
SELECT service FROM Employe rend cinq lignes en SQL, avec Etudes et Support deux fois chacune. La projection algébrique en rend trois.
La traduction fidèle de π est donc SELECT DISTINCT. SQL s'écarte ici de l'algèbre dont il dérive, comme il le fait avec NULL, ou avec une table sans clé, qui peut contenir deux fois la même ligne. Il a deux raisons de garder les doublons. Dédoublonner coûte cher, et le moteur ne le fait que si on le lui demande. Et les doublons comptent dès qu'on additionne ou qu'on fait une moyenne : deux salaires égaux pèsent deux fois dans la masse salariale.
1.Que rend π_{ville}(Etudiant), sachant que la table contient dix étudiants répartis sur quatre villes ?
2.Quelle écriture SQL traduit fidèlement la projection algébrique ?
3.σ_{¬(note > 10)}(Inscription) retient-elle les lignes dont la note vaut NULL ?
Le dédoublonnage ne fait pas qu'alléger un résultat : il peut fausser un calcul fait dessus. Le raisonnement suivant semble tenir, et une de ses étapes ne tient pas.
Une masse salariale qui fond
Une seule étape est fausse. Désigner laquelle.
Un service compte employés, tous payés 2 000 € par mois. La direction veut sa masse salariale, la somme des salaires de ses employés, et la tire d'une expression d'algèbre.
Renommage (ρ)
Le renommage change le nom d'un attribut sans toucher aux données. ρ_{salaireMensuel ← salaire}(Employe) se lit : « Employe, où l'attribut salaire s'appelle désormais salaireMensuel ». Il sert quand deux relations portent le même nom d'attribut et qu'il faut les distinguer.
Cliquer sur un nœud pour voir la relation qu'il produit.
| idEmploye | nom | prenom | salaireMensuel | date_embauche | service |
|---|---|---|---|---|---|
| 1 | Girard | Nadia | 2450 | 2019-04-01 | Etudes |
| 2 | Lemoine | Paul | 1980 | 2021-09-15 | Support |
| 3 | Barbier | Sofia | 3100 | 2016-01-10 | Etudes |
| 4 | Roche | Tom | 2200 | 2022-03-07 | Support |
| 5 | Vidal | Lucie | 2750 | 2018-11-23 | Commerce |
On peut aussi renommer une relation entière. ρ_{E2}(Employe) désigne une seconde copie d'Employe, dont les attributs s'appellent E2.nom, E2.service, et ainsi de suite. Cela sert à combiner une table avec elle-même, ce que la jointure permettra plus bas.
Produit cartésien (×)
Le produit associe chaque ligne de gauche à chaque ligne de droite. Client × Projet se lit : « chaque client apparié à chaque projet, sans aucune condition ». C'est bien le problème : le résultat compte le produit des deux effectifs.
Cliquer sur un nœud pour voir la relation qu'il produit.
| Client.idClient | nom | prenom | ville | idProjet | libelle | Projet.idClient |
|---|---|---|---|---|---|---|
| 1 | Durand | Paul | Paris | 1 | Portail client | 1 |
| 1 | Durand | Paul | Paris | 2 | Refonte ERP | 2 |
| 1 | Durand | Paul | Paris | 3 | Application mobile | 3 |
| 1 | Durand | Paul | Paris | 4 | Audit reseau | 4 |
| 2 | Leroy | Sarah | Lyon | 1 | Portail client | 1 |
| 2 | Leroy | Sarah | Lyon | 2 | Refonte ERP | 2 |
| 2 | Leroy | Sarah | Lyon | 3 | Application mobile | 3 |
| 2 | Leroy | Sarah | Lyon | 4 | Audit reseau | 4 |
| 3 | Moreau | Karim | Paris | 1 | Portail client | 1 |
| 3 | Moreau | Karim | Paris | 2 | Refonte ERP | 2 |
| 3 | Moreau | Karim | Paris | 3 | Application mobile | 3 |
| 3 | Moreau | Karim | Paris | 4 | Audit reseau | 4 |
| 4 | Fontaine | Eva | Bordeaux | 1 | Portail client | 1 |
| 4 | Fontaine | Eva | Bordeaux | 2 | Refonte ERP | 2 |
| 4 | Fontaine | Eva | Bordeaux | 3 | Application mobile | 3 |
| 4 | Fontaine | Eva | Bordeaux | 4 | Audit reseau | 4 |
Sur seize lignes, seules quatre associent un projet à son vrai client. Les douze autres sont du bruit. Le produit cartésien n'est presque jamais ce qu'on veut ; il est en revanche la brique dont la jointure est faite.
Jointure (⨝)
La jointure est un produit cartésien suivi d'une sélection. La condition s'écrit en indice, exactement comme pour σ. Client ⨝_{Client.idClient = Projet.idClient} Projet se lit : « chaque client apparié aux projets qui portent son identifiant ». Avec une condition quelconque, on parle de thêta-jointure ; quand la condition est une égalité, comme ici, d'équijointure.
Cliquer sur un nœud pour voir la relation qu'il produit.
| Client.idClient | nom | prenom | ville | idProjet | libelle | Projet.idClient |
|---|---|---|---|---|---|---|
| 1 | Durand | Paul | Paris | 1 | Portail client | 1 |
| 2 | Leroy | Sarah | Lyon | 2 | Refonte ERP | 2 |
| 3 | Moreau | Karim | Paris | 3 | Application mobile | 3 |
| 4 | Fontaine | Eva | Bordeaux | 4 | Audit reseau | 4 |
Écrite sans condition, la jointure devient naturelle : elle apparie sur tous les attributs qui portent le même nom des deux côtés, et ne garde qu'un exemplaire de ces attributs.
Cliquer sur un nœud pour voir la relation qu'il produit.
| idClient | nom | prenom | ville | idProjet | libelle |
|---|---|---|---|---|---|
| 1 | Durand | Paul | Paris | 1 | Portail client |
| 2 | Leroy | Sarah | Lyon | 2 | Refonte ERP |
| 3 | Moreau | Karim | Paris | 3 | Application mobile |
| 4 | Fontaine | Eva | Bordeaux | 4 | Audit reseau |
La jointure naturelle dépend entièrement des noms de colonnes. Ajouter demain une colonne dateCreation aux deux tables changerait silencieusement l'appariement, et donc le résultat, sans qu'aucune requête ait été modifiée. Et deux tables qui ne partagent aucun nom d'attribut n'ont rien à égaler : leur jointure naturelle garde toutes les paires, c'est un produit cartésien, et rien ne le signale. Employe ⨝ Classe rend ainsi quinze lignes, cinq employés fois trois classes.
En pratique, écrire la condition explicitement coûte une ligne et évite cette classe de surprise.
Le nombre de lignes d'un produit ne dépend que des effectifs ; celui d'une jointure dépend des valeurs qui s'apparient. Les deux se prévoient avant de cliquer.
Prévoir la taille d'un résultat
- 1.
Une agence compte 1 200 clients et 3 500 projets. Combien de lignes le produit
Client × Projetcompte-t-il ? - 2.
Chaque projet a un seul client, qui existe. Combien de lignes compte la jointure sur
idClient? - 3.
Combien de lignes du produit la condition d'appariement jette-t-elle ?
- 4.
Inscriptiona 3 attributs etCours5, avec un seul nom en commun,idCours. Combien d'attributs compte la jointure naturelleInscription ⨝ Cours?
La jointure peut aussi apparier une table avec elle-même, grâce au renommage d'une relation vu plus haut. Les paires d'employés qui travaillent dans le même service s'obtiennent en joignant Employe à sa copie E2 :
Cliquer sur un nœud pour voir la relation qu'il produit.
| Employe.nom | E2.nom |
|---|---|
| Girard | Barbier |
| Lemoine | Roche |
Opérations ensemblistes (∪, ∩, −)
L'union, l'intersection et la différence se comportent comme sur des ensembles ordinaires. Elles exigent que les deux relations aient le même schéma : le même nombre d'attributs, appariés dans l'ordre, de domaines compatibles (des nombres face à des nombres, du texte face à du texte), et qui désignent la même chose.
Les trois se lisent en une phrase chacune. Inscrits ∪ Boursiers : « les noms qui figurent dans au moins une des deux listes ». Inscrits ∩ Boursiers : « ceux qui figurent dans les deux ». Inscrits − Boursiers : « ceux qui figurent dans la première et pas dans la seconde ».
Cliquer sur un nœud pour voir la relation qu'il produit.
| nom |
|---|
| Martin |
| Diallo |
| Dupond |
| Nguyen |
Cliquer sur un nœud pour voir la relation qu'il produit.
| nom |
|---|
| Diallo |
Cliquer sur un nœud pour voir la relation qu'il produit.
| nom |
|---|
| Martin |
| Dupond |
Compter une union, une intersection, une différence
- 1.
Une association étudiante tient deux listes de même schéma : 120 adhérents et 45 bénévoles, dont 30 figurent sur les deux. Combien de lignes rend
Adherents ∪ Benevoles? - 2.
Combien en rend
Adherents − Benevoles? - 3.
Et
Benevoles − Adherents?
Le moteur de ces figures vérifie ce qu'il peut : le nombre d'attributs, puis, colonne par colonne, qu'un nombre ne se retrouve pas face à un texte. TravailleSur et Projet ont trois attributs chacun, mais leur union rangerait des libellés de projet parmi des identifiants : il la refuse.
Cliquer sur un nœud pour voir la relation qu'il produit.
Échec attendu.opérandes non compatibles : la colonne 2 contient des nombres à gauche (idProjet) et du texte à droite (libelle). Les colonnes s'apparient une à une, dans l'ordre, et chaque paire doit avoir le même domaine.
Le sens, en revanche, lui échappe. Des noms de clients et des noms de villes sont tous du texte : π_{nom}(Client) ∪ π_{ville}(Client) passe sans erreur, et rend un mélange qui ne veut rien dire. Vérifier que deux colonnes parlent de la même chose reste le travail de celui qui écrit l'union.
∪ s'écrit UNION, ∩ INTERSECT et − EXCEPT. Contrairement à SELECT, ces trois opérations dédoublonnent d'elles-mêmes, comme l'algèbre ; UNION ALL est la variante qui garde les doublons. MySQL connaît INTERSECT et EXCEPT depuis sa version 8.0.31.
SQL est en revanche moins strict que l'algèbre sur le schéma. MySQL et SQLite ne vérifient que le nombre de colonnes : ils les apparient par position et gardent les noms de la première requête. SELECT * FROM TravailleSur UNION SELECT * FROM Projet s'y exécute sans un mot, et range « Refonte ERP » sous l'en-tête idProjet. PostgreSQL, lui, refuse d'apparier un entier et un texte. Dans tous les cas, le sens reste à vérifier soi-même.
La différence est l'opération qui permet d'exprimer une négation. « Les cours sans enseignant affecté » se traduit par une différence entre tous les cours et ceux qui en ont un. Ceux qui en ont un, c'est la jointure qui les trouve : elle ne garde un cours que si son enseignant existe.
Cliquer sur un nœud pour voir la relation qu'il produit.
| idCours | intitule |
|---|---|
| 4 | Physique |
| 7 | Reseaux |
idCours reste dans les deux projections, et ce n'est pas un détail. Sur intitule seul, deux cours de même intitulé, l'un avec enseignant et l'autre sans, se confondraient, et la différence ferait disparaître le second.
Division (÷)
Le besoin apparaît dès qu'une question contient « tous les » : tous les projets d'une liste, toutes les compétences exigées, tous les cours d'un programme. Une jointure répond à « au moins un », ce qui est une question différente et plus large. Les opérations déjà vues savent répondre à « tous les », mais au prix d'un détour par deux différences ; la division donne un nom et un symbole à ce détour.
La division prend deux relations : le dividende R, et le diviseur S, dont tous les attributs figurent aussi dans R. Elle rend les valeurs des autres attributs de R qui sont associées à toutes les lignes de S. Le cas le plus courant, celui de la figure, met deux attributs à gauche et un à droite. Affectation ÷ Tous se lit : « les employés qui travaillent sur tous les projets listés dans Tous ».
Six affectations d'un côté, deux projets exigés de l'autre.
Cliquer sur un nœud pour voir la relation qu'il produit.
| employe |
|---|
| Nadia |
| Sofia |
Le calcul se fait employé par employé. Pour chacun, rassembler ses projets, puis vérifier que les deux projets exigés y figurent tous les deux. C'est le tableau intermédiaire que la notation cache.
| employé | ses projets | Portail ? | Mobile ? | retenu ? |
|---|---|---|---|---|
| Nadia | Portail, Mobile | oui | oui | oui |
| Paul | Portail | oui | non | non |
| Sofia | Portail, Mobile, ERP | oui | oui | oui |
Trois employés examinés, deux retenus. Deux enseignements se lisent dans ce tableau. Paul est écarté par une seule case à « non » : il suffit qu'un seul élément du diviseur manque. Sofia est retenue malgré ERP, qui n'est pas dans le diviseur : la division exige au moins les projets listés, pas exactement ceux-là.
Un diviseur vide ne disqualifie personne : il ne manque rien à aucun candidat, et tous sont retenus. Une question en « tous les » sur une liste qui peut être vide demande donc un contrôle à part.
Noter enfin que la colonne projet a disparu du résultat, qui ne porte plus que employe. C'est la règle : la division retire les attributs du diviseur et ne garde que les autres.
La division n'ajoute pourtant rien à ce que l'algèbre sait déjà faire : elle se récrit avec π, × et −. On fabrique tous les couples qui devraient exister, chaque employé avec chaque projet exigé ; on retire ceux qui existent vraiment ; il reste les couples manquants, et l'employé d'un couple manquant n'est pas retenu.
Cliquer sur un nœud pour voir la relation qu'il produit.
| employe |
|---|
| Nadia |
| Sofia |
C'est l'opération que personne ne retient, parce qu'elle est la seule à ne pas avoir de mot-clé SQL. On l'y écrit justement par ce détour, devenu une double négation : les employés pour lesquels il n'existe pas de projet de la liste auquel ils ne participent pas. Cette formulation lourde est ce que la division résume en un symbole.
Compter les couples manquants est le cœur du calcul, et c'est là qu'un raisonnement rapide dérape.
Des couples manquants qui disparaissent
Une seule étape est fausse. Désigner laquelle.
Dans la figure de la division, trois employés et deux projets exigés. Affectation contient 5 couples sur ces deux projets, et couples des mêmes employés sur d'autres projets, comme Sofia sur ERP. Il s'agit de compter les couples manquants, ceux qui écartent un employé.
La division, comptée à la main
- 1.
Une plateforme de formation compte 40 apprentis inscrits à au moins un module, et une certification exige 3 modules précis. Combien de couples (apprenti, module exigé) la division doit-elle vérifier ?
- 2.
100 de ces couples figurent parmi les inscriptions. Combien de couples manquent ?
- 3.
Combien d'apprentis la division écarte-t-elle au plus ?
- 4.
Et au moins, sachant qu'un apprenti n'a que 3 couples attendus, donc au plus 3 couples manquants ?
1.Le moteur accepte π_{nom}(Client) ∪ π_{ville}(Client) sans erreur. Que manque-t-il à cette union pour avoir un sens ?
2.EmployeCompetence ÷ Competence rend :
3.Aucun client n'habite Nantes. Que rend π_{idEmploye, idProjet}(TravailleSur) divisé par les projets des clients nantais ?
Le tableau récapitulatif
| Opération | Notation | Effet sur les lignes | Effet sur les colonnes |
|---|---|---|---|
| Sélection | σ_{condition}(R) | en garde certaines | inchangées |
| Projection | π_{attributs}(R) | dédoublonne | n'en garde que certaines |
| Renommage | ρ_{b ← a}(R), ρ_{R2}(R) | inchangées | en renomme une, ou renomme la relation |
| Produit | R × S | multiplie les effectifs | concatène les deux schémas |
| Jointure | R ⨝_{condition} S | apparie | concatène les deux schémas (la naturelle ne garde qu'une fois les attributs communs) |
| Union | R ∪ S | rassemble, dédoublonne | schéma commun exigé |
| Intersection | R ∩ S | garde le commun | schéma commun exigé |
| Différence | R − S | retire | schéma commun exigé |
| Division | R ÷ S | garde ce qui couvre tout S | retire les attributs de S |
| Jointure externe gauche | R ⟕_{condition} S | apparie, et garde aussi les lignes de R sans partenaire, complétées par NULL | concatène les deux schémas |
La dernière ligne n'a pas d'écriture dans le moteur des arbres. La figure suivante la montre à côté de la jointure ordinaire, sur les cours et leurs enseignants ; le chapitre sur les requêtes SQL la pratique sous le nom de LEFT JOIN.
LEFT JOIN … ON garde toutes les lignes de gauche, complétées par des NULL à droite quand rien ne correspond.
Cours(gauche, 7 lignes)
| idCours | intitule | volumeHoraire | coefficient | idEnseignant |
|---|---|---|---|---|
| 1 | Bases de donnees | 30 | 2 | 1 |
| 2 | Algorithmique | 24 | 1.5 | 2 |
| 3 | Mathematiques | 36 | 2.5 | 3 |
| 4 | Physique | 27 | 2 | NULL |
| 5 | Informatique | 30 | 2 | 1 |
| 6 | Statistiques | 18 | 1 | 3 |
| 7 | Reseaux | 21 | 1.5 | NULL |
Enseignant(droite, 3 lignes)
| idEnseignant | nomEns | prenomEns | specialite |
|---|---|---|---|
| 1 | Durand | Claire | Bases de donnees |
| 2 | Ferrand | Marc | Algorithmique |
| 3 | Aubert | Sophie | Statistiques |
ON Cours.idEnseignant = Enseignant.idEnseignant
| idCours | intitule | volumeHoraire | coefficient | Cours.idEnseignant | Enseignant.idEnseignant | nomEns | prenomEns | specialite |
|---|---|---|---|---|---|---|---|---|
| 1 | Bases de donnees | 30 | 2 | 1 | 1 | Durand | Claire | Bases de donnees |
| 2 | Algorithmique | 24 | 1.5 | 2 | 2 | Ferrand | Marc | Algorithmique |
| 3 | Mathematiques | 36 | 2.5 | 3 | 3 | Aubert | Sophie | Statistiques |
| 4 | Physique | 27 | 2 | NULL | NULL | NULL | NULL | NULL |
| 5 | Informatique | 30 | 2 | 1 | 1 | Durand | Claire | Bases de donnees |
| 6 | Statistiques | 18 | 1 | 3 | 3 | Aubert | Sophie | Statistiques |
| 7 | Reseaux | 21 | 1.5 | NULL | NULL | NULL | NULL | NULL |
- NULL en orange : fabriqué par la jointure. Cette valeur n'est nulle part dans la base, elle comble la place d'une ligne qui n'existe pas.
SELECT *
FROM Cours
LEFT JOIN Enseignant
ON Cours.idEnseignant = Enseignant.idEnseignant1.Une jointure R ⨝ S sous condition équivaut à :
2.Deux tables de 200 et 50 lignes. Combien de lignes compte leur produit cartésien ?
Composer, et donc dessiner
La clôture permet d'emboîter. L'expression suivante enchaîne trois opérations : une jointure, une sélection, une projection. Elle se lit de l'intérieur vers l'extérieur : « apparier chaque étudiant à sa classe, ne garder que la classe 1A, puis n'afficher que le nom et le prénom ».
Cliquer sur un nœud pour voir la relation qu'il produit.
| nom | prenom |
|---|---|
| Martin | Lea |
| Diallo | Amine |
| Dupond | Sophie |
| Petit | Sofia |
L'arbre se lit de bas en haut. Les feuilles sont les tables telles qu'elles sont stockées ; chaque nœud consomme le résultat du niveau inférieur ; la racine porte le résultat final.
| Élément | Rôle |
|---|---|
| Feuilles | les tables de la base |
| Nœuds internes | les opérations, σ π ρ ⨝ × ∪ ∩ − ÷ |
| Arêtes | l'ordre d'évaluation, du bas vers le haut |
| Racine | le résultat rendu |
Cet arbre est aussi la façon dont un moteur représente une requête avant de l'exécuter. Le lire, c'est lire la forme logique du plan d'exécution ; le plan réel y ajoute le choix des algorithmes et des index, que le chapitre Exploiter une base fait lire. Et si le moteur se donne la peine de choisir entre plusieurs arbres, c'est qu'ils ne se valent pas.
Optimiser : pousser les sélections vers les feuilles
Voici la raison pour laquelle ce chapitre existe. Deux arbres peuvent rendre exactement le même résultat en faisant un travail très différent. Le nombre de lignes affiché à chaque nœud le montre directement. On compare le plus gros résultat intermédiaire, c'est-à-dire le nœud d'opération le plus large : les feuilles sont lues de toute façon, et aucune réécriture ne les réduit.
Soit à nouveau la question : le nom et le prénom des étudiants de la classe 1A. Première écriture, la plus naïve : tout combiner, puis filtrer le tas.
Cliquer sur un nœud pour voir la relation qu'il produit.
| nom | prenom |
|---|---|
| Martin | Lea |
| Diallo | Amine |
| Dupond | Sophie |
| Petit | Sofia |
Deuxième écriture : remplacer le produit par une jointure, ce qui revient à effectuer une partie du filtrage plus tôt.
Cliquer sur un nœud pour voir la relation qu'il produit.
| nom | prenom |
|---|---|
| Martin | Lea |
| Diallo | Amine |
| Dupond | Sophie |
| Petit | Sofia |
Troisième écriture : filtrer Classe avant de joindre. La sélection descend jusqu'à la feuille.
Cliquer sur un nœud pour voir la relation qu'il produit.
| nom | prenom |
|---|---|
| Martin | Lea |
| Diallo | Amine |
| Dupond | Sophie |
| Petit | Sofia |
Modifier l'expression, puis « Recalculer » : l'arbre se redessine sur les mêmes tables.
Les trois arbres rendent les quatre mêmes lignes, et la troisième version ne fabrique aucune ligne intermédiaire inutile. Sur une base de démonstration, la différence de temps est invisible ; sur dix mille étudiants et cent classes, la version 1 construit un million de lignes pour en garder une centaine.
Ce que coûte chaque version
- 1.
Une enseigne a 50 000 commandes et 200 magasins, et cherche les commandes du magasin de Lille. Combien de lignes le produit
Commande × Magasinde la version naïve fabrique-t-il ? - 2.
Chaque commande vient d'un seul magasin. Combien de lignes construit la jointure de la deuxième version ?
- 3.
La troisième version filtre d'abord
Magasin, qui ne garde que Lille. Si les commandes se répartissent également entre les magasins, combien de lignes sa jointure construit-elle ? - 4.
Combien de fois la troisième version construit-elle moins de lignes que la première ?
Les règles de réécriture.
- Découper les conjonctions.
σ_{a ∧ b}(R)rend la même relation queσ_{a}(σ_{b}(R)), et chaque morceau descend ensuite vers la feuille qui porte ses attributs : c'est ce découpage qui fait passer de la version 1 à la version 3. Une disjonction ne se découpe pas : une conditionσ_{a ∨ b}qui mélange deux tables reste entière au-dessus de leur jointure. - Descendre les sélections le plus près possible des feuilles. Filtrer avant de combiner est toujours au moins aussi bon.
- Remplacer produit puis sélection par une jointure. C'est la même opération, mais le moteur peut l'exécuter sans matérialiser le produit.
- Descendre les projections, en gardant les attributs dont les opérations supérieures ont besoin. Moins de colonnes transportées, moins de mémoire. En pratique, le moteur descend les projections sans dédoublonner, ce qui coûterait cher, et ne dédoublonne qu'à la racine, si
DISTINCTest demandé. - Commencer par la jointure la plus sélective quand il y en a plusieurs, pour que les suivantes travaillent sur peu de lignes.
Toutes ces règles disent la même chose : jeter tôt ce qui sera jeté de toute façon.
La règle des projections se voit aussi dans la figure, qui affiche à chaque nœud son nombre d'attributs. Sur la même question, une quatrième version ne laisse entrer dans la jointure que ce qui sert plus haut.
Cliquer sur un nœud pour voir la relation qu'il produit.
| nom | prenom |
|---|---|
| Martin | Lea |
| Diallo | Amine |
| Dupond | Sophie |
| Petit | Sofia |
L'ordre compte sous la jointure de droite : la sélection sur nomClasse doit passer avant la projection π_{idClasse}, qui retire justement nomClasse. Et idClasse reste dans les deux projections, parce que la condition de jointure en a besoin, même si la racine ne l'affiche pas.
1.Où placer une sélection pour qu'un arbre coûte le moins cher possible ?
2.Dans σ_{nomClasse = '1A' ∨ ville = 'Lyon'}(Etudiant ⨝ Classe), peut-on descendre ville = 'Lyon' sur la feuille Etudiant ?
Un arbre à plusieurs jointures
Les trois versions précédentes n'avaient que deux tables. Le gain devient beaucoup plus net dès qu'il y en a davantage, puisque chaque jointure travaille sur ce que la précédente lui a laissé.
Objectif : le nom des étudiants inscrits à un cours dispensé par l'enseignante Durand. Quatre tables, trois jointures.
Cliquer sur un nœud pour voir la relation qu'il produit.
| nom |
|---|
| Martin |
| Diallo |
| Dupond |
| Lefebvre |
| Moreau |
| Marchand |
| Nguyen |
Remarquer la projection finale : sept lignes contre huit pour la jointure qu'elle surmonte. Un étudiant inscrit à deux cours de Durand y figurait deux fois, et le dédoublonnage les confond. Il confondrait de même deux étudiants qui portent le même nom ; projeter sur idEtudiant, nom l'éviterait.
Trois arbres rendent le même résultat ; leur plus gros résultat intermédiaire compte 30, 10 et 4 lignes. Lequel choisir ?
Écrire des expressions, et les faire vérifier
Six exercices, du plus simple au plus composé, sur les tables du cours. Chacun s'écrit dans sa zone de saisie, au clavier ou avec la barre de symboles. « Vérifier » calcule l'expression sur plusieurs versions des tables, et la compare à la correction calculée sur les mêmes : une expression juste écrite autrement que la correction, jointure naturelle, sélection placée ailleurs, colonnes dans un autre ordre, est acceptée. Chaque version qui change une table la montre sous son libellé ; une version cachée ne dit que si elle passe, et démasque une expression écrite pour les seules données affichées. L'arbre de l'expression vérifiée se dessine sous le verdict, et se lit nœud par nœud comme les figures. Des indices s'ouvrent un par un ; une correction, après deux vérifications ou une réussite.
Les villes des étudiants, sans répétition
La scolarité prépare une carte des lieux de résidence. Écrire l'expression qui donne les villes où résident des étudiants (attribut ville d'Etudiant), chacune une seule fois.
Une condition ou une liste d'attributs s'écrit en indice, entre accolades, une chaîne entre apostrophes, un nombre décimal avec un point. Au clavier, et, ou, non, <>, <=, >= et le tiret de la différence conviennent aussi.
Écrire l'expression, puis « Vérifier » : elle est calculée sur 3 cas, dont 1 caché, et comparée à la correction calculée sur les mêmes tables.
Les tables du cas « une étudiante de plus, installée à Lille »
| idEtudiant | nom | prenom | dateNaissance | ville | idClasse | actif | |
|---|---|---|---|---|---|---|---|
| 1 | Martin | Lea | 2004-03-12 | lea.martin@ecole.fr | Paris | 1 | 1 |
| 2 | Diallo | Amine | 2003-11-02 | amine.diallo@ecole.fr | Lyon | 1 | 1 |
| 3 | Dupond | Sophie | 2004-07-25 | sophie.dupond@ecole.fr | Paris | 1 | 1 |
| 4 | Durand | Tom | 2003-05-30 | tom.durand@ecole.fr | Nantes | 2 | 0 |
| 5 | Lefebvre | Ines | 2004-01-18 | ines.lefebvre@ecole.fr | Lyon | 2 | 1 |
| 6 | Bernard | Yanis | 2002-09-08 | NULL | Paris | 2 | 1 |
| 7 | Moreau | Chi | 2004-02-14 | chi.moreau@ecole.fr | Paris | 3 | 1 |
| 8 | Marchand | Hugo | 2003-08-21 | NULL | Bordeaux | 3 | 1 |
| 9 | Nguyen | Elsa | 2004-11-30 | elsa.nguyen@ecole.fr | Lyon | 3 | 1 |
| 10 | Petit | Sofia | 2002-12-05 | sofia.petit@ecole.fr | Nantes | 1 | 0 |
| 11 | Roux | Ines | 2004-06-03 | ines.roux@ecole.fr | Lille | 2 | 1 |
Les autres tables sont celles du cours.
Les employés du support bien payés
Le service du personnel prépare la revue des salaires du support. Écrire l'expression qui donne les employés du service Support dont le salaire dépasse 2 000 €, avec tous leurs attributs.
Une condition ou une liste d'attributs s'écrit en indice, entre accolades, une chaîne entre apostrophes, un nombre décimal avec un point. Au clavier, et, ou, non, <>, <=, >= et le tiret de la différence conviennent aussi.
Écrire l'expression, puis « Vérifier » : elle est calculée sur 3 cas, dont 1 caché, et comparée à la correction calculée sur les mêmes tables.
Les tables du cas « un salaire relevé, une mutation, une embauche à 2 000 € »
| idEmploye | nom | prenom | salaire | date_embauche | service |
|---|---|---|---|---|---|
| 1 | Girard | Nadia | 2450 | 2019-04-01 | Etudes |
| 2 | Lemoine | Paul | 2100 | 2021-09-15 | Support |
| 3 | Barbier | Sofia | 3100 | 2016-01-10 | Etudes |
| 4 | Roche | Tom | 2200 | 2022-03-07 | Support |
| 5 | Vidal | Lucie | 2750 | 2018-11-23 | Support |
| 6 | Noel | Ada | 2000 | 2024-02-12 | Support |
Les autres tables sont celles du cours.
Les étudiants parisiens et leur classe
Écrire l'expression qui donne le nom de chaque étudiant habitant Paris, avec le nom de sa classe (nomClasse).
Une condition ou une liste d'attributs s'écrit en indice, entre accolades, une chaîne entre apostrophes, un nombre décimal avec un point. Au clavier, et, ou, non, <>, <=, >= et le tiret de la différence conviennent aussi.
Écrire l'expression, puis « Vérifier » : elle est calculée sur 3 cas, dont 1 caché, et comparée à la correction calculée sur les mêmes tables.
Les tables du cas « Chi Moreau passe en 1A, Ines Lefebvre s'installe à Paris »
| idEtudiant | nom | prenom | dateNaissance | ville | idClasse | actif | |
|---|---|---|---|---|---|---|---|
| 1 | Martin | Lea | 2004-03-12 | lea.martin@ecole.fr | Paris | 1 | 1 |
| 2 | Diallo | Amine | 2003-11-02 | amine.diallo@ecole.fr | Lyon | 1 | 1 |
| 3 | Dupond | Sophie | 2004-07-25 | sophie.dupond@ecole.fr | Paris | 1 | 1 |
| 4 | Durand | Tom | 2003-05-30 | tom.durand@ecole.fr | Nantes | 2 | 0 |
| 5 | Lefebvre | Ines | 2004-01-18 | ines.lefebvre@ecole.fr | Paris | 2 | 1 |
| 6 | Bernard | Yanis | 2002-09-08 | NULL | Paris | 2 | 1 |
| 7 | Moreau | Chi | 2004-02-14 | chi.moreau@ecole.fr | Paris | 1 | 1 |
| 8 | Marchand | Hugo | 2003-08-21 | NULL | Bordeaux | 3 | 1 |
| 9 | Nguyen | Elsa | 2004-11-30 | elsa.nguyen@ecole.fr | Lyon | 3 | 1 |
| 10 | Petit | Sofia | 2002-12-05 | sofia.petit@ecole.fr | Nantes | 1 | 0 |
Les autres tables sont celles du cours.
Les cours de plus de 24 heures et leur enseignant
Écrire l'expression qui donne l'intitulé de chaque cours de plus de 24 heures (volumeHoraire), avec le nom de son enseignant (nomEns).
Une condition ou une liste d'attributs s'écrit en indice, entre accolades, une chaîne entre apostrophes, un nombre décimal avec un point. Au clavier, et, ou, non, <>, <=, >= et le tiret de la différence conviennent aussi.
Écrire l'expression, puis « Vérifier » : elle est calculée sur 3 cas, dont 1 caché, et comparée à la correction calculée sur les mêmes tables.
Les tables du cas « la physique reçoit un enseignant »
| idCours | intitule | volumeHoraire | coefficient | idEnseignant |
|---|---|---|---|---|
| 1 | Bases de donnees | 30 | 2 | 1 |
| 2 | Algorithmique | 24 | 1.5 | 2 |
| 3 | Mathematiques | 36 | 2.5 | 3 |
| 4 | Physique | 27 | 2 | 2 |
| 5 | Informatique | 30 | 2 | 1 |
| 6 | Statistiques | 18 | 1 | 3 |
| 7 | Reseaux | 21 | 1.5 | NULL |
Les autres tables sont celles du cours.
Les clients sans projet
Le service commercial veut relancer les clients avec qui l'entreprise n'a encore aucun projet. Écrire l'expression qui donne leur identifiant, idClient.
Sur les tables du cours, les quatre clients ont chacun un projet : la réponse juste y est une relation vide, ce qui n'est pas une erreur, mais la réponse « personne ».
Une condition ou une liste d'attributs s'écrit en indice, entre accolades, une chaîne entre apostrophes, un nombre décimal avec un point. Au clavier, et, ou, non, <>, <=, >= et le tiret de la différence conviennent aussi.
Écrire l'expression, puis « Vérifier » : elle est calculée sur 3 cas, dont 1 caché, et comparée à la correction calculée sur les mêmes tables.
Les tables du cas « avec un cinquième client, qui n'a pas encore de projet »
| idClient | nom | prenom | ville |
|---|---|---|---|
| 1 | Durand | Paul | Paris |
| 2 | Leroy | Sarah | Lyon |
| 3 | Moreau | Karim | Paris |
| 4 | Fontaine | Eva | Bordeaux |
| 5 | Durand | Lea | Lyon |
Les autres tables sont celles du cours.
Les employés affectés à tous les projets
Écrire l'expression qui donne l'identifiant (idEmploye) des employés qui travaillent sur tous les projets de la table Projet. Un employé affecté en plus à d'autres travaux reste retenu.
Une condition ou une liste d'attributs s'écrit en indice, entre accolades, une chaîne entre apostrophes, un nombre décimal avec un point. Au clavier, et, ou, non, <>, <=, >= et le tiret de la différence conviennent aussi.
Écrire l'expression, puis « Vérifier » : elle est calculée sur 3 cas, dont 1 caché, et comparée à la correction calculée sur les mêmes tables.
Les tables du cas « Barbier rejoint les deux projets qui lui manquaient »
| idEmploye | idProjet | heures |
|---|---|---|
| 1 | 1 | 120 |
| 1 | 3 | 40 |
| 2 | 1 | 80 |
| 3 | 2 | 200 |
| 3 | 3 | 60 |
| 4 | 4 | 35 |
| 5 | 2 | 90 |
| 3 | 1 | 10 |
| 3 | 4 | 5 |
Les autres tables sont celles du cours.
Ressources complémentaires
- INSA Rouen, cours SGBD. Un support complet sur les systèmes de gestion de bases de données et l'algèbre relationnelle. Algèbre relationnelle, INSA Rouen
- Bertrand Liaudet, INSIA. Optimisation et arbres algébriques, avec exemples et exercices. Le site d'origine, à l'université de Cergy-Pontoise, ne répond plus ; le lien mène à une copie archivée. Arbres algébriques, copie archivée
- DB Fiddle. Un environnement pour exécuter des requêtes SQL et comparer leurs résultats. db-fiddle.com
Mettre en pratique
Cliquer sur un nœud pour voir la relation qu'il produit.
| prenom | nom |
|---|---|
| Tom | Durand |
| Sofia | Petit |
Lire l'arbre ci-dessus et en donner la requête SQL
De bas en haut : partir de Etudiant, ne garder que les lignes dont actif vaut 0, puis n'afficher que le prénom et le nom.
Le DISTINCT traduit la projection. Ici il ne change rien, les deux étudiants concernés ayant des noms différents, mais l'écriture reste la traduction fidèle.
Améliorer cet arbre
L'expression suivante donne le bon résultat, mais fait travailler la jointure pour rien.
Cliquer sur un nœud pour voir la relation qu'il produit.
| nom |
|---|
| Diallo |
| Lefebvre |
| Nguyen |
La condition ville = 'Lyon' ne porte que sur Etudiant. Rien n'oblige à attendre la jointure pour l'appliquer.
Cliquer sur un nœud pour voir la relation qu'il produit.
| nom |
|---|
| Diallo |
| Lefebvre |
| Nguyen |
Le résultat est identique. Le travail intermédiaire est divisé par trois sur cette petite base, et dans le même rapport que la sélectivité du filtre sur une grande. Descendre aussi les projections, π_{nom, idClasse} sur Etudiant et π_{idClasse} sur Classe, ne laisserait passer dans la jointure que trois attributs au lieu de onze.
Pourquoi π_{nom}(Etudiant × Client) échoue-t-il ?
Parce que nom désigne deux colonnes différentes après le produit : celle de Etudiant et celle de Client. L'expression est ambiguë, et le moteur le signale plutôt que de choisir au hasard.
Cliquer sur un nœud pour voir la relation qu'il produit.
Échec attendu.attribut ambigu : nom désigne Etudiant.nom et Client.nom. Préciser la table, par exemple Etudiant.nom
Deux façons de lever l'ambiguïté. Qualifier l'attribut :
Cliquer sur un nœud pour voir la relation qu'il produit.
| nom |
|---|
| Martin |
| Diallo |
| Dupond |
| Durand |
| Lefebvre |
| Bernard |
| Moreau |
| Marchand |
| Nguyen |
| Petit |
Ou renommer avant de combiner, ce qui vaut mieux quand l'expression est longue :
Cliquer sur un nœud pour voir la relation qu'il produit.
| nomEtudiant |
|---|
| Martin |
| Diallo |
| Dupond |
| Durand |
| Lefebvre |
| Bernard |
| Moreau |
| Marchand |
| Nguyen |
| Petit |
Qualifier ne suffit plus quand les deux colonnes viennent de la même table : dans Client × Client, les deux colonnes s'appellent Client.nom. Le moteur le dit, et conseille de renommer l'une des deux copies par ρ, comme pour la jointure d'Employe avec sa copie E2.
Chapitre révisé en octobre 2026 · Une erreur dans ce chapitre ?
Dans la bibliothèque d'exercices
Écrire ses premières expressions, compter les lignes d'un résultat, le bruit du produit, pousser la sélection, dire « sans » et « tous les », retrouver les notes qui manquent, joindre une table à sa copie renommée, traduire une requête à deux jointures, et les pièges du NULL et de l'union.
- Les employés du supportNiveau 2
- Compter les lignes d'un résultatNiveau 2
- Le bruit du produit cartésienNiveau 2
- Le cours qui n'est ni d'un côté ni de l'autreNiveau 2
- Les notes qui manquentNiveau 3
- Les clients d'une même villeNiveau 3
- Dire « sans » en algèbreNiveau 3
- Une union acceptée n'est pas une union justeNiveau 3
- Pousser la sélection vers les feuillesNiveau 3
- De SQL vers l'algèbre, deux jointuresNiveau 3
- Les couples qui manquentNiveau 3
- Tous les projets des clients parisiensNiveau 4