Workshop, les arbres algébriques
Ce que ce chapitre apporte4 points
- Employer chaque opérateur fondamental isolément, puis en combinaison.
- Choisir l'ordre d'application des opérations, et savoir lequel est imposé.
- Lire un arbre algébrique et le construire à partir d'un énoncé en français.
- Réécrire un arbre en un arbre équivalent qui travaille moins.
Un chapitre entièrement d'exercices. Chaque énoncé se traite dans le même ordre : lire la question en français, écrire l'expression algébrique, la dessiner en arbre, puis la pousser vers une forme moins coûteuse. Les corrigés sont repliés et calculés : chaque arbre affiché se clique, nœud par nœud, pour voir la relation qu'il produit. Les ouvrir après avoir cherché, pas avant.
Le contrat de chaque exercice
- L'énoncé donne les données sur lesquelles travailler, ou renvoie explicitement à la base de démonstration du module.
- Il se termine par une ligne Vérification : le nombre de lignes et de colonnes que rend l'expression juste. Elle tient le rôle des
assertdes ateliers de programmation. Une expression qui ne rend pas ce compte est fausse, même si elle semble dire la bonne chose. - La correction est repliée sous l'énoncé. Chaque arbre qu'elle contient se clique nœud par nœud, et affiche la relation produite à cet étage : c'est là qu'on voit à quel moment une expression dérape.
- Chercher d'abord, comparer à la ligne Vérification, ouvrir la correction ensuite. Les trois niveaux se suivent, chacun supposant le précédent traité.
Déroulé
| Temps indicatif | Niveau | Ce qui est travaillé |
|---|---|---|
| 30 min | Niveau 1, exercices 1 à 5 | un opérateur à la fois : σ, π, ∪, −, × |
| 45 min | Niveau 2, exercices 6 à 9 | enchaîner plusieurs opérations, et poser une division |
| 45 min | Niveau 3, exercices 10 à 14 | lire un arbre, en construire un, le réécrire moins coûteux |
Prévoir environ deux heures pour l'ensemble, corrections comprises.
Rappel des notations
| Opérateur | Symbole | Effet |
|---|---|---|
| Sélection | σ | filtre les lignes selon une condition |
| Projection | π | ne garde que certaines colonnes, et dédoublonne |
| Renommage | ρ | change le nom d'un attribut |
| Union | ∪ | réunit deux relations de même schéma, sans doublon |
| Intersection | ∩ | ne garde que ce qui figure des deux côtés |
| Différence | − | retire de la gauche ce que porte la droite |
| Produit cartésien | × | toutes les combinaisons de lignes |
| Jointure | ⨝ | produit filtré par une condition d'appariement |
| Division | ÷ | ce qui est lié à tous les éléments d'une autre relation |
Une expression s'évalue de l'intérieur vers l'extérieur, comme en mathématiques.
Dans π_{nom}(σ_{ville = 'Paris'}(Client)), lire d'abord Client, puis la sélection, puis la projection. Sur l'arbre, cela revient à partir des feuilles et à remonter jusqu'à la racine.
Niveau 1, un opérateur à la fois
Ces exercices portent sur les opérateurs de base, isolément. L'objectif est la syntaxe et l'effet exact de chaque opération sur les lignes et sur les colonnes.
Exercice 1, sélection
Relation Produit :
| idProduit | nom | prix |
|---|---|---|
| 1 | Clavier | 45 |
| 2 | Souris | 30 |
| 3 | Ecran | 220 |
- Écrire une expression qui garde uniquement les produits dont le prix dépasse strictement 40.
- Nommer les produits retenus.
- Modifier l'expression pour garder ceux dont le prix ne dépasse pas 100.
Vérification. Les deux expressions rendent chacune deux lignes et gardent les trois colonnes. Ce ne sont pas les deux mêmes lignes.
Afficher la correction
La sélection filtre les lignes et laisse le schéma intact : les trois colonnes restent.
Cliquer sur un nœud pour voir la relation qu'il produit.
| idProduit | nom | prix |
|---|---|---|
| 1 | Clavier | 45 |
| 3 | Ecran | 220 |
Pour la seconde condition, seul le comparateur change.
Cliquer sur un nœud pour voir la relation qu'il produit.
| idProduit | nom | prix |
|---|---|---|
| 1 | Clavier | 45 |
| 2 | Souris | 30 |
Exercice 2, projection
Toujours avec Produit :
- Écrire une projection qui ne garde que
nometprix. - Une projection peut-elle réduire le nombre de lignes ? Justifier.
- Écrire une projection qui ne garde que
idProduit.
Vérification. Sur les trois produits ci-dessus, les deux projections rendent trois lignes, l'une sur deux colonnes, l'autre sur une seule. La question 2 porte sur le cas, absent de cette table, où ce compte tomberait plus bas.
Afficher la correction
Cliquer sur un nœud pour voir la relation qu'il produit.
| nom | prix |
|---|---|
| Clavier | 45 |
| Souris | 30 |
| Ecran | 220 |
Oui, une projection peut réduire le nombre de lignes. Une relation est un ensemble : si la projection efface ce qui distinguait deux lignes, elles se confondent. Il suffit d'ajouter une seconde souris au même prix pour le voir.
Cliquer sur un nœud pour voir la relation qu'il produit.
| nom | prix |
|---|---|
| Clavier | 45 |
| Souris | 30 |
| Ecran | 220 |
Sur idProduit, qui est une clé, aucune fusion n'est possible.
Cliquer sur un nœud pour voir la relation qu'il produit.
| idProduit |
|---|
| 1 |
| 2 |
| 3 |
Exercice 3, union
Deux relations de même schéma. Client(nom) contient Alice et Bernard ; Prospect(nom) contient Bernard et Camille.
- Écrire l'expression qui rassemble tous les noms présents dans l'une ou l'autre.
- Donner le résultat attendu, nom par nom.
- Dire ce qui se passe si les deux relations n'ont pas les mêmes colonnes.
Vérification. Quatre lignes entrent, trois sortent.
Afficher la correction
Cliquer sur un nœud pour voir la relation qu'il produit.
| nom |
|---|
| Alice |
| Bernard |
| Camille |
L'union est une opération ensembliste : elle exige le même schéma, c'est-à-dire le même nombre d'attributs, dans le même ordre, de types compatibles. Sans cela, on ne saurait pas quelle colonne du résultat correspond à quoi. Le moteur refuse l'opération.
Exercice 4, différence
Mêmes relations.
- Écrire l'expression qui garde les clients qui ne sont pas aussi prospects.
- Donner le résultat.
- La différence est-elle symétrique ? Justifier par un exemple.
Vérification. Une seule ligne dans un sens, une seule dans l'autre, et ce n'est pas la même.
Afficher la correction
Cliquer sur un nœud pour voir la relation qu'il produit.
| nom |
|---|
| Alice |
Non, la différence n'est pas symétrique. L'inverse donne un résultat entièrement différent.
Cliquer sur un nœud pour voir la relation qu'il produit.
| nom |
|---|
| Camille |
L'union, elle, est symétrique : A ∪ B et B ∪ A donnent la même relation.
Exercice 5, produit cartésien
Auteur(nom) contient Camus et Duras. Livre(titre) contient La Peste, L Etranger et Le Ravissement.
- Écrire le produit cartésien des deux.
- Dire combien de lignes le résultat compte, et pourquoi ce compte ne dépend pas des données.
- Expliquer pourquoi ce produit devient une jointure utile une fois filtré.
Vérification. Six lignes et deux colonnes.
Afficher la correction
Cliquer sur un nœud pour voir la relation qu'il produit.
| nom | titre |
|---|---|
| Camus | La Peste |
| Camus | L Etranger |
| Camus | Le Ravissement |
| Duras | La Peste |
| Duras | L Etranger |
| Duras | Le Ravissement |
Le produit associe tout à tout, sans se soucier de ce qui va ensemble. Il n'a donc aucune signification métier tel quel. En lui appliquant une sélection qui ne retient que les paires réellement liées, on obtient exactement une jointure :
R ⨝_{condition} S = σ_{condition}(R × S)
C'est la définition de la jointure, et la raison pour laquelle le produit cartésien mérite d'être compris malgré son inutilité apparente.
Niveau 2, combiner les opérateurs
Les exercices suivants enchaînent plusieurs opérations. La question devient : dans quel ordre ? Certains ordres sont imposés par la disponibilité des colonnes ; parmi ceux qui restent, tous ne coûtent pas la même chose.
À partir d'ici, les exercices portent sur la base de démonstration du module, celle des chapitres SQL. Les résultats affichés sont donc ceux que rendraient les requêtes correspondantes.
Exercice 6, jointure simple
Relations Employe(idEmploye, nom, prenom, salaire, date_embauche, service) et, côté projets, TravailleSur(idEmploye, idProjet, heures) et Projet(idProjet, libelle, idClient).
- Écrire une expression qui associe à chaque affectation le libellé du projet concerné.
- Expliquer pourquoi une union ne conviendrait pas ici.
- Réécrire l'expression pour ne garder que le nom de l'employé et le libellé du projet.
Vérification. La première expression rend sept lignes et six colonnes, la troisième sept lignes et deux colonnes.
Afficher la correction
Cliquer sur un nœud pour voir la relation qu'il produit.
| idEmploye | TravailleSur.idProjet | heures | Projet.idProjet | libelle | idClient |
|---|---|---|---|---|---|
| 1 | 1 | 120 | 1 | Portail client | 1 |
| 1 | 3 | 40 | 3 | Application mobile | 3 |
| 2 | 1 | 80 | 1 | Portail client | 1 |
| 3 | 2 | 200 | 2 | Refonte ERP | 2 |
| 3 | 3 | 60 | 3 | Application mobile | 3 |
| 4 | 4 | 35 | 4 | Audit reseau | 4 |
| 5 | 2 | 90 | 2 | Refonte ERP | 2 |
Une union est impossible : elle exige deux relations de même schéma, or TravailleSur a trois attributs et Projet trois autres, qui ne désignent pas les mêmes choses. La jointure, elle, est faite pour rapprocher des relations de schémas différents partageant une valeur.
Pour obtenir le nom de l'employé, une seconde jointure est nécessaire, puisque TravailleSur ne porte qu'un identifiant.
Cliquer sur un nœud pour voir la relation qu'il produit.
| nom | libelle |
|---|---|
| Girard | Portail client |
| Girard | Application mobile |
| Lemoine | Portail client |
| Barbier | Refonte ERP |
| Barbier | Application mobile |
| Roche | Audit reseau |
| Vidal | Refonte ERP |
Exercice 7, sélection et jointure
Objectif : le nom des employés affectés au projet Refonte ERP.
- Écrire l'expression complète.
- Expliquer pourquoi la sélection sur le libellé ne peut pas s'appliquer directement à
TravailleSur. - Proposer une version qui filtre avant de joindre, et dire ce qu'elle gagne.
Vérification. Deux lignes et une colonne, dans les deux versions. Ce qui change est la taille du nœud de jointure le plus large : sept lignes d'un côté, deux de l'autre.
Afficher la correction
Première écriture, la plus directe : joindre les trois tables, puis filtrer.
Cliquer sur un nœud pour voir la relation qu'il produit.
| nom |
|---|
| Barbier |
| Vidal |
L'attribut libelle n'existe que dans Projet. Tant que la jointure n'a pas eu lieu, aucune ligne de TravailleSur ne le porte, et la sélection n'a rien sur quoi s'appliquer. L'ordre est donc imposé ici : joindre Projet avant de filtrer sur libelle.
En revanche, rien n'oblige à joindre Projet en dernier. Filtrer Projet d'abord, puis joindre, donne le même résultat pour beaucoup moins de travail.
Cliquer sur un nœud pour voir la relation qu'il produit.
| nom |
|---|
| Barbier |
| Vidal |
C'est le principe de la poussée de sélection : la condition descend le long de l'arbre jusqu'à la feuille dont elle dépend.
Exercice 8, division
EmployeCompetence(employe, competence) contient les couples Alice-Java, Alice-SQL, Alice-Reseau, Paul-Java, Paul-SQL et Chi-Java. Competence(competence) contient Java et SQL.
- Écrire une expression qui identifie les employés possédant toutes les compétences listées.
- Dire ce que cette opération permet et que les autres ne permettent pas.
- Expliquer pourquoi Chi est exclue, et pourquoi Alice ne l'est pas malgré sa compétence supplémentaire.
Vérification. Deux lignes et une seule colonne, employe.
Afficher la correction
Cliquer sur un nœud pour voir la relation qu'il produit.
| employe |
|---|
| Alice |
| Paul |
La division exprime une quantification universelle : « pour tout élément du diviseur, il existe une association dans le dividende ». Ni la sélection ni la jointure ne savent dire « tous ». Une jointure répondrait à « au moins un », ce qui est une question différente.
SQL n'a pas de mot-clé pour la division. On la traduit par une double négation : les employés pour lesquels il n'existe pas de compétence de la liste qu'ils ne possèdent pas.
Chi est exclue parce qu'il existe une compétence de la liste, SQL, qu'elle ne possède pas. Une seule manquante suffit.
Exercice 9, jointure et division
Objectif : le nom des étudiants inscrits à tous les cours de coefficient 1,5.
- Écrire l'expression, en deux étapes.
- Dire pourquoi la division est indispensable.
- Expliquer pourquoi une projection doit précéder la division.
Vérification. La division rend une ligne. L'expression complète rend une ligne et deux colonnes.
Afficher la correction
Première étape, identifier les cours concernés, puis diviser.
Cliquer sur un nœud pour voir la relation qu'il produit.
| idEtudiant |
|---|
| 3 |
Seconde étape, récupérer le nom par une jointure sur l'identifiant obtenu.
Cliquer sur un nœud pour voir la relation qu'il produit.
| nom | prenom |
|---|---|
| Dupond | Sophie |
La division est indispensable parce que la question porte sur tous les cours. Une jointure seule rendrait les étudiants inscrits à au moins un de ces cours, ce qui est une réponse différente et plus large.
Inscription porte trois attributs : idEtudiant, idCours et note. Écrire directement Inscription ÷ π_{idCours}(Cours) ferait entrer note dans le calcul : le résultat serait constitué de couples (idEtudiant, note) couvrant tous les cours, autrement dit d'étudiants ayant obtenu exactement la même note dans tous les cours de la liste.
La projection sur les deux seuls attributs utiles évite cette confusion. C'est la règle générale : avant une division, réduire le dividende aux attributs concernés.
Niveau 3, les arbres
Un arbre algébrique est le dessin d'une expression. La racine porte l'opération finale, les feuilles sont les tables, les nœuds internes les opérations intermédiaires. Il se lit de bas en haut.
Descendre les sélections au plus près des feuilles, et descendre les projections dès que les attributs supérieurs le permettent. Les deux disent la même chose : réduire tôt ce qui sera réduit de toute façon, pour que les opérations coûteuses travaillent sur moins.
Exercice 10, lecture d'un arbre
Cliquer sur un nœud pour voir la relation qu'il produit.
| nom | prenom |
|---|---|
| Durand | Paul |
| Moreau | Karim |
- Décrire étape par étape ce que fait cet arbre.
- Dire ce qui se passe si la projection et la sélection sont inversées.
- Conclure sur l'interchangeabilité des deux opérations.
Vérification. L'arbre donné rend deux lignes et deux colonnes. L'arbre inversé n'en rend aucune : il échoue, et c'est précisément la réponse à la question 2.
Afficher la correction
De bas en haut : partir de Client (quatre lignes), ne garder que les clients parisiens (deux lignes), puis n'afficher que le nom et le prénom.
Inversées, l'expression devient σ_{ville = 'Paris'}(π_{nom, prenom}(Client)). Après la projection, la colonne ville a disparu : la sélection n'a plus rien sur quoi porter.
Cliquer sur un nœud pour voir la relation qu'il produit.
Échec attendu.attribut inconnu : ville. Disponibles : nom, prenom
Les deux opérations ne sont donc pas librement interchangeables. Une projection ne peut descendre sous une sélection que si elle conserve les attributs dont cette sélection a besoin. En pratique, on descend les projections en gardant les colonnes utilisées plus haut, quitte à les projeter une seconde fois à la racine.
Exercice 11, construire un arbre simple
Objectif : le nom et le prénom des clients ayant au moins un projet.
- Donner l'expression algébrique.
- Décrire l'arbre correspondant.
- Nommer l'opération centrale et dire pourquoi elle est nécessaire.
Vérification. Quatre lignes et deux colonnes.
Afficher la correction
Cliquer sur un nœud pour voir la relation qu'il produit.
| nom | prenom |
|---|---|
| Durand | Paul |
| Leroy | Sarah |
| Moreau | Karim |
| Fontaine | Eva |
L'opération centrale est la jointure. Sans elle, l'information reste séparée : Projet ne contient pas le nom du client, Client ne contient pas la liste de ses projets. Seul l'identifiant partagé permet de les rapprocher.
Noter que la jointure fait ici un travail de filtre en plus de son travail d'appariement. Un client sans aucun projet ne figurerait pas dans le résultat, aucune ligne de Projet ne lui correspondant.
Exercice 12, sélection et jointures multiples
Objectif : le nom des étudiants inscrits au cours Mathematiques.
- Donner une expression complète.
- Décrire l'arbre non optimisé.
- Proposer une version optimisée et expliquer le gain.
Vérification. Cinq lignes et une colonne, dans les deux versions. Le nœud le plus large passe de vingt-cinq lignes à cinq.
Afficher la correction
Version non optimisée : joindre les trois tables, puis filtrer sur l'intitulé.
Cliquer sur un nœud pour voir la relation qu'il produit.
| nom |
|---|
| Martin |
| Diallo |
| Dupond |
| Bernard |
| Nguyen |
Version optimisée : filtrer Cours avant de joindre. La sélection descend jusqu'à la feuille dont elle dépend.
Cliquer sur un nœud pour voir la relation qu'il produit.
| nom |
|---|
| Martin |
| Diallo |
| Dupond |
| Bernard |
| Nguyen |
Le résultat est identique. Le nœud le plus large passe de 25 à 5 lignes, et l'écart croît avec la taille de la base. Sur mille cours et cent mille inscriptions, la première version construit cent mille lignes intermédiaires pour en garder quelques dizaines.
Exercice 13, lire et transformer
Cliquer sur un nœud pour voir la relation qu'il produit.
| nom |
|---|
| Moreau |
| Marchand |
| Nguyen |
- Nommer les nœuds internes et les feuilles.
- Dire ce qu'il faudrait changer pour afficher aussi le prénom.
- Dire ce qu'il faudrait changer pour filtrer sur le prénom au lieu du nom de classe.
Vérification. L'arbre de départ rend trois lignes et une colonne. Avec le prénom ajouté, trois lignes et deux colonnes. En filtrant sur prenom = 'Chi', une seule ligne.
Afficher la correction
Les feuilles sont Etudiant et Classe. Les nœuds internes sont la jointure et la sélection. La racine est la projection π_{nom}.
Pour afficher aussi le prénom, seule la projection change. prenom appartient déjà à Etudiant, qui figure dans l'arbre : rien d'autre à toucher.
Cliquer sur un nœud pour voir la relation qu'il produit.
| nom | prenom |
|---|---|
| Moreau | Chi |
| Marchand | Hugo |
| Nguyen | Elsa |
Pour filtrer sur le prénom, la situation est meilleure qu'il n'y paraît. prenom appartient à Etudiant, donc la sélection n'a pas besoin d'attendre la jointure : elle peut descendre directement sur la feuille.
Cliquer sur un nœud pour voir la relation qu'il produit.
| nom | nomClasse |
|---|---|
| Moreau | 2A |
C'est la différence entre les deux cas. nomClasse vient de Classe, donc une sélection dessus doit se placer au-dessus de la jointure ou sur la feuille Classe. prenom vient de Etudiant : sa sélection descend de l'autre côté.
Exercice 14, d'un besoin à un arbre
Objectif : le nom des employés du service Etudes ayant travaillé plus de 100 heures sur un projet.
- Lister les opérations nécessaires, dans l'ordre logique.
- Donner l'expression complète, déjà optimisée.
- Décrire l'arbre obtenu.
Vérification. Deux lignes et une colonne. La version bien ordonnée fait travailler la jointure sur deux lignes de chaque côté, la version naïve sur cinq et sept.
Afficher la correction
Les opérations, dans l'ordre :
- filtrer les employés du service
Etudes, sur la feuilleEmploye; - filtrer les affectations de plus de 100 heures, sur la feuille
TravailleSur; - joindre les deux résultats sur
idEmploye; - projeter le nom.
Les deux sélections sont indépendantes et portent chacune sur une feuille différente : elles descendent toutes les deux.
Cliquer sur un nœud pour voir la relation qu'il produit.
| nom |
|---|
| Girard |
| Barbier |
Pour mesurer le gain, la même question écrite sans réfléchir à l'ordre :
Cliquer sur un nœud pour voir la relation qu'il produit.
| nom |
|---|
| Girard |
| Barbier |
Les deux arbres rendent les deux mêmes lignes. Le premier fait travailler la jointure sur deux lignes de chaque côté, le second sur cinq et sept. Sur une base réelle, ce rapport est celui de la sélectivité des deux filtres, et il se compte souvent en ordres de grandeur.
La méthode
- Lire l'énoncé et repérer le mot qui porte la question : « seulement ceux qui » appelle une sélection, « le nom de » une projection, « et son » une jointure, « tous les » une division.
- Lister les tables nécessaires et vérifier, attribut par attribut, laquelle porte chaque colonne citée par l'énoncé. Une colonne sans table est le signe qu'il manque une jointure.
- Poser les jointures d'abord, chacune avec sa condition d'appariement écrite en toutes lettres.
- Placer chaque sélection sur la feuille dont elle dépend. Ne laisser au-dessus de la jointure que les conditions qui mélangent deux tables.
- Projeter en dernier, en n'écrivant que les attributs demandés, et se rappeler que la projection dédoublonne.
- Compter le résultat à la main et le comparer à la ligne Vérification de l'énoncé, avant d'ouvrir la correction.
- Cliquer le nœud le plus large de l'arbre et chercher l'opération qui le ferait rétrécir. Recommencer tant qu'il en reste une.
Synthèse
- σ agit sur les lignes et laisse le schéma intact. π agit sur les colonnes, et peut réduire le nombre de lignes par dédoublonnage, puisqu'une relation est un ensemble.
- ∪, ∩ et − exigent deux relations de même schéma. Seule la différence dépend de l'ordre de ses opérandes.
- × associe tout à tout et n'a aucun sens métier tel quel. Une sélection posée dessus en fait exactement une jointure, ce qui est sa définition.
- ⨝ rapproche deux schémas différents sur une valeur partagée, et écarte au passage ce qui ne s'apparie pas : c'est un filtre autant qu'un assemblage.
- ÷ traduit un « pour tous ». Réduire le dividende par une projection aux seuls attributs concernés, sans quoi la question posée change en silence.
- Un ordre est imposé quand une opération réclame un attribut qu'une autre produit ou détruit : filtrer sur
libelleexige d'avoir jointProjet, filtrer survilleinterdit d'avoir déjà projeté sans elle. - Parmi les ordres possibles, tous ne coûtent pas la même chose. Une sélection descend jusqu'à la feuille dont elle dépend ; une projection descend tant que les opérations supérieures n'ont plus besoin des colonnes retirées.
- Un arbre se lit de bas en haut : les feuilles sont les tables, les nœuds internes les opérations, la racine le résultat rendu.
- Deux arbres équivalents se comparent au nombre de lignes de leur nœud le plus large, jamais à leur résultat, qui est le même par construction.
Quiz
1.π_{nom, prix}(Produit) peut-il rendre moins de lignes que Produit ?
2.Pourquoi une union entre Employe et Projet est-elle impossible ?
3.σ_{ville = 'Paris'}(π_{nom, prenom}(Client)) échoue. Pourquoi ?
4.Dans π_{nom}(σ_{libelle = 'Refonte ERP'}(TravailleSur ⨝ Projet)), la sélection peut-elle descendre sous la jointure ?
5.Avant une division, pourquoi projeter le dividende ?
6.Une jointure entre Client et Projet écarte-t-elle un client sans projet ?
7.Deux arbres donnent le même résultat. Le premier a un nœud à 25 lignes, le second à 5. Que conclure ?