logo

Workshop - Algèbre et arbres relationnels

Niveau 1 – Fondamentaux

Exercice 1 – Sélection

Relation Produit :

idProduit nom prix
1 Clavier 45
2 Souris 30
3 Écran 220
  1. Donne une expression d’algèbre relationnelle permettant de garder uniquement les produits dont le prix est strictement supérieur à 40.
  2. Quels produits seront affichés ?
  3. Modifie l’expression pour garder uniquement ceux dont le prix est inférieur ou égal à 100.
Correction
1. σ_{prix > 40}(Produit)

2. Résultat :
| idProduit | nom     | prix |
|-----------|---------|------|
| 1         | Clavier | 45   |
| 3         | Écran   | 220  |

3. σ_{prix ≤ 100}(Produit)

Exercice 2 – Projection

Toujours avec la relation Produit :

  1. Donne une expression de projection pour ne garder que les colonnes nom et prix.
  2. Est-ce que cette opération peut réduire le nombre de lignes ? Explique.
  3. Donne une autre projection qui ne garde que la colonne idProduit.
Correction
1. π_{nom, prix}(Produit)

2. Oui, si plusieurs lignes ont le même nom et prix, elles seront fusionnées.
Exemple : deux produits avec nom = "Souris" et prix = 30 apparaîtront qu’une seule fois.

3. π_{idProduit}(Produit)

Exercice 3 – Union

Deux relations :

Client(nom)
Prospect(nom)
Client Prospect
nom nom
Alice Bernard
Bernard Camille
  1. Donne une expression permettant de rassembler tous les noms présents dans l’une ou l’autre table.
  2. Quel est le résultat final attendu ?
  3. Que se passe-t-il si les deux relations n’ont pas les mêmes colonnes ?
Correction
1. Client ∪ Prospect

2. Résultat :
| nom     |
|---------|
| Alice   |
| Bernard |
| Camille |

→ Les doublons sont supprimés automatiquement.

3. L’union n’est possible que si les deux relations ont le **même nombre et ordre de colonnes** (même schéma). Sinon, l’opération est invalide.

Exercice 4 – Différence

Même relations Client(nom) et Prospect(nom) :

  1. Donne une expression pour garder uniquement les clients qui ne sont pas aussi prospects.
  2. Quel est le résultat final ?
  3. Est-ce que la différence est symétrique ? Explique avec un exemple.
Correction
1. Client − Prospect

2. Résultat :
| nom   |
|-------|
| Alice |

→ Alice est cliente mais pas prospecte.

3. Non, la différence n’est pas symétrique :

- Client − Prospect = { Alice }
- Prospect − Client = { Camille }

→ L’ordre est important.

Exercice 5 – Produit cartésien

Relations :

Auteurs(nom)
Livres(titre)
  1. Écris l’opération de produit cartésien entre les deux relations.
  2. Si la première relation contient 2 lignes et la seconde en contient 3, combien de lignes le résultat contiendra-t-il ?
  3. Pourquoi ce produit peut-il ensuite être filtré pour devenir une jointure utile ?
Correction
1. Auteurs × Livres

2. 2 auteurs × 3 livres = 6 lignes.

3. Le produit cartésien associe tous les auteurs à tous les livres.
→ Ce n’est utile que si on applique ensuite un **filtre** (ex. : "cet auteur a écrit ce livre") pour obtenir des correspondances réelles.
→ Cela donne alors une jointure (produit + sélection).

Niveau 2 – Requêtes combinées

Exercice 6 – Jointure simple

Relations :

Employe(id, nom, idDept)
Departement(idDept, nomDept)
  1. Écris une expression permettant d’associer à chaque employé le nom de son département.
  2. Pourquoi ne peut-on pas utiliser une union dans ce cas ?
  3. Réécris l’expression pour ne garder que le nom de l’employé et celui de son département.
Correction
1. Employe ⨝_{Employe.idDept = Departement.idDept} Departement

2. Une union n’est possible que si les deux relations ont **le même schéma** (mêmes colonnes). Ce n’est pas le cas ici.

3. π_{nom, nomDept}(Employe ⨝_{Employe.idDept = Departement.idDept} Departement)

Exercice 7 – Sélection + Jointure

Relations :

Employe(id, nom, idDept)
Departement(idDept, nomDept)
  1. Donne une expression d’algèbre relationnelle complète pour obtenir les noms des employés travaillant dans le département RH.
  2. Pourquoi faut-il faire la jointure avant la sélection sur le nom du département ?
  3. Peux-tu inverser les deux opérations ? Justifie.
Correction
1. π_{nom}(σ_{nomDept = "RH"}(Employe ⨝_{Employe.idDept = Departement.idDept} Departement))

2. Le filtre porte sur "nomDept", qui n’existe que dans Departement. Il faut donc faire la jointure d’abord pour avoir accès à ce champ dans les résultats.

3. On ne peut pas filtrer sur un champ qui n’existe pas encore dans la relation : il est donc obligatoire de faire la jointure d’abord.

Exercice 8 – Division (cas classique)

Relations :

EmployeCompetence(employe, competence)
Competence(competence)
  1. Donne une expression qui permet d’identifier les employés qui possèdent toutes les compétences listées dans la relation Competence.
  2. Que permet cette opération, que ne permettent pas les autres (sélection, jointure…) ?
  3. Ajoute une ligne dans EmployeCompetence pour un employé avec seulement une partie des compétences et explique pourquoi il ne sera pas gardé.
Correction
1. EmployeCompetence ÷ Competence

2. La division permet de **trouver les individus (employés ici) qui ont un lien avec tous les éléments d’un autre ensemble** (toutes les compétences). C’est une recherche globale.

3. Si Competence contient {A, B, C}, et que "Paul" n’a que A et B, il ne sera pas dans le résultat car il n’a **pas toutes** les compétences demandées.

Exercice 9 – Jointure + Division (cas d’inscriptions)

Relations :

Cours(idCours, nomCours)
Inscription(idEtudiant, idCours)
Etudiant(idEtudiant, nom)
  1. Donne une expression permettant de récupérer les étudiants inscrits à tous les cours existants.
  2. Quelle opération principale dois-tu utiliser ? Explique.
  3. Comment améliorerais-tu le modèle si tu voulais aussi associer un enseignant à chaque cours ?
Correction
1. π_{idEtudiant}(Inscription ÷ π_{idCours}(Cours))

→ puis jointure pour retrouver leur nom :
π_{nom}(Etudiant ⨝_{idEtudiant}(Inscription ÷ π_{idCours}(Cours)))

2. La division est nécessaire ici pour vérifier qu’un étudiant est lié à **toutes les lignes** de la relation Cours.

3. On peut ajouter une relation :
Enseignement(idCours, idProf)

→ Cela permettrait d’associer chaque cours à un enseignant.

Niveau 3 – Arbres algébriques

Exercice 10 – Lecture d’un arbre algébrique

Arbre :

       π_{nom, prenom}
              |
     σ_{ville = 'Paris'}
              |
           Client
  1. Explique étape par étape ce que fait cet arbre.
  2. Que se passe-t-il si on inverse la projection et la sélection ?
  3. Quelle serait la différence de résultat ou de performance dans ce cas ?
Correction
1. Étapes :
- On commence avec la relation Client.
- On filtre uniquement les clients dont la ville est "Paris".
- On garde ensuite uniquement les colonnes "nom" et "prenom".

2. Si on projette avant la sélection, on risque de **perdre la colonne "ville"**, donc on **ne pourra plus filtrer**.

3. Conclusion : on doit **toujours garder les colonnes utiles aux filtres** avant de projeter.

Exercice 11 – Construction d’un arbre simple

Relations :

Commande(idCommande, idClient)
Client(idClient, nom, prenom)

Objectif : afficher le nom et prénom des clients ayant passé une commande.

  1. Donne l’expression en algèbre relationnelle.
  2. Dessine un arbre algébrique correspondant.
  3. Quelle est l’opération principale à la base de cet arbre ? Pourquoi ?
Correction
1. π_{nom, prenom}(Client ⨝_{Client.idClient = Commande.idClient} Commande)

2. Arbre :

        π_{nom, prenom}
               |
    ⨝_{Client.idClient = Commande.idClient}
           /           \
        Client       Commande

3. L’opération centrale est la **jointure**, car elle permet d’associer chaque commande à son client.

Exercice 12 – Arbre avec sélection + jointure

Relations :

Etudiant(id, nom, prenom)
Inscription(idEtudiant, idCours)
Cours(idCours, nomCours)

Objectif : obtenir le nom des étudiants inscrits au cours "Maths".

  1. Donne une expression complète.
  2. Dessine un arbre algébrique correspondant.
  3. Propose une version optimisée de l’arbre.
Correction
1. π_{nom}(Etudiant ⨝ Inscription ⨝ σ_{nomCours = "Maths"}(Cours))

2. Arbre :

         π_{nom}
            |
     ⨝ (Etudiant.id = Inscription.idEtudiant)
            |
     ⨝ (Inscription.idCours = Cours.idCours)
            |
      σ_{nomCours = "Maths"}
            |
           Cours

        (les autres branches : Etudiant et Inscription)

3. Optimisation :
→ Appliquer la sélection sur "Maths" **le plus tôt possible** (directement sur la relation Cours), pour éviter de traiter des données inutiles.

Exercice 13 – Lecture et transformation d’arbre

Arbre :

          π_{nom}
             |
    σ_{nomClasse = '2A'}
             |
⨝_{Etudiant.idClasse = Classe.idClasse}
         /            \
     Etudiant        Classe
  1. Quels sont les nœuds internes et les feuilles de cet arbre ?
  2. Si on voulait afficher aussi le prénom, que faudrait-il changer ?
  3. Et si on voulait filtrer sur le prénom au lieu du nom de la classe ?
Correction
1. Feuilles : Etudiant, Classe
   Nœuds internes : jointure, sélection, projection

2. Changer la projection :
π_{nom, prenom}(...)

3. Déplacer ou modifier la sélection :
σ_{prenom = '...'}

→ Elle doit se faire **après la jointure** si le champ est uniquement présent dans Etudiant.

Exercice 14 – Création d’un arbre à partir d’un besoin

Relations :

Client(id, nom, ville)
Commande(idCommande, idClient, montant)

Objectif : afficher le nom des clients qui habitent à Lyon et ont passé une commande de plus de 1000.

  1. Quelles sont les opérations nécessaires ?
  2. Donne l’expression algébrique complète.
  3. Dessine l’arbre correspondant.
Correction
1. Opérations :
- Sélection sur la ville
- Sélection sur le montant
- Jointure entre Client et Commande
- Projection du nom

2. Expression complète :

π_{nom}(σ_{montant > 1000}(Commande) ⨝ σ_{ville = "Lyon"}(Client))

3. Arbre :

           π_{nom}
              |
           ⨝ (Client.id = Commande.idClient)
           /                              \
σ_{ville = "Lyon"}                    σ_{montant > 1000}
      |                                     |
    Client                              Commande