Classe SDA 7 2025-2026
Dans le module précédent, nous avons intelligemment séparé nos données dans des tables distinctes pour éviter la redondance. C'est la bonne pratique. Mais cela crée un nouveau défi : comment répondre à une question simple qui nécessite des informations de plusieurs tables ?
"Afficher le nom de chaque client à côté du nom du produit qu'il a commandé."
Le nom du client est dans la table utilisateurs. Le nom du produit est dans la table commandes. La jointure (JOIN) est l'opération SQL magique qui nous permet de "reconstituer" temporairement une vue unifiée de ces tables en se basant sur leur relation.
Pour tous les exemples suivants, nous utiliserons ces deux tables :
| id | nom |
|---|---|
| 1 | Alice |
| 2 | Bob |
| 3 | Charlie |
| id | produit | utilisateur_id |
|---|---|---|
| 101 | Livre | 1 |
| 102 | Ordinateur | 2 |
| 103 | Stylo | 1 |
| 104 | Clavier | 4 |
Notez que Charlie (id=3) n'a pas de commande, et que la commande de Clavier (id=104) a un utilisateur_id (4) qui n'existe pas dans notre table utilisateurs.
Ce qu'elle fait : Renvoie uniquement les lignes pour lesquelles il existe une correspondance dans les deux tables. C'est la jointure la plus courante et la plus restrictive.
Question type : "Montre-moi uniquement les utilisateurs QUI ONT passé une commande, et les produits qu'ils ont achetés."
Visualisation Venn : La zone centrale où les deux cercles se chevauchent.
Résultat :
| nom | produit |
|---|---|
| Alice | Livre |
| Bob | Ordinateur |
| Alice | Stylo |
(Charlie est exclu car il n'a pas de correspondance dans commandes. La commande "Clavier" est exclue car son utilisateur_id 4 n'a pas de correspondance dans utilisateurs.)
Ce qu'elle fait : Renvoie toutes les lignes de la table de gauche (celle déclarée dans FROM), et les lignes correspondantes de la table de droite. S'il n'y a pas de correspondance à droite, les colonnes de cette table seront remplies avec la valeur NULL.
Question type : "Montre-moi tous les utilisateurs, et affiche les commandes qu'ils ont passées, s'ils en ont."
Visualisation Venn : Le cercle entier de gauche, y compris la partie qui intersecte le cercle de droite.
Résultat :
| nom | produit |
|---|---|
| Alice | Livre |
| Alice | Stylo |
| Bob | Ordinateur |
| Charlie | NULL |
(Charlie apparaît maintenant, car il est dans la table de gauche, mais avec NULL pour le produit car il n'a pas de commande correspondante.)
Ce qu'elle fait : C'est l'inverse exact du LEFT JOIN. Elle renvoie toutes les lignes de la table de droite (celle déclarée dans JOIN), et les correspondances de la table de gauche.
Question type : "Montre-moi toutes les commandes, et le nom de l'utilisateur qui les a passées, s'il existe."
Résultat :
| nom | produit |
|---|---|
| Alice | Livre |
| Bob | Ordinateur |
| Alice | Stylo |
| NULL | Clavier |
(La commande "Clavier" apparaît maintenant, car elle est dans la table de droite, mais avec NULL pour le nom car son utilisateur_id 4 n'existe pas dans la table utilisateurs.)
Ce qu'elle fait : Renvoie toutes les lignes des deux tables. Lorsqu'il y a une correspondance, les données des deux côtés sont affichées. Lorsqu'il n'y a pas de correspondance, des NULL apparaissent du côté manquant.
Question type : "Montre-moi tous les utilisateurs ET toutes les commandes, qu'ils soient liés ou non."
Visualisation Venn : Les deux cercles en entier.
Résultat :
| nom | produit |
|---|---|
| Alice | Livre |
| Alice | Stylo |
| Bob | Ordinateur |
| Charlie | NULL |
| NULL | Clavier |
Note : MySQL ne supporte pas directement FULL OUTER JOIN. Vous pouvez obtenir le même résultat en combinant LEFT JOIN et RIGHT JOIN avec UNION.
Dans les applications réelles, vous devrez souvent joindre trois tables ou plus. La logique reste la même : vous enchaînez simplement plusieurs JOIN.
Imaginons que nous ajoutons une table categories pour classifier nos produits :
Ici, nous lions trois tables en chaînant deux INNER JOIN. L'ordre des jointures est important pour la lisibilité, mais SQL optimisera l'exécution automatiquement.
Si vous omettez la condition ON, vous créerez un produit cartésien : chaque ligne de la première table sera associée à chaque ligne de la seconde table. Pour 100 utilisateurs et 1000 commandes, cela génère 100 000 lignes !
Rappelez-vous : LEFT JOIN garde toutes les lignes de la table de gauche (après FROM), RIGHT JOIN garde toutes les lignes de la table de droite (après JOIN).
Astuce : La plupart des développeurs utilisent principalement LEFT JOIN car c'est plus intuitif (on part de la table principale). Un RIGHT JOIN peut toujours être réécrit comme un LEFT JOIN en inversant l'ordre des tables.
Si deux tables ont des colonnes avec le même nom (comme id), vous devez toujours préciser à quelle table appartient la colonne en utilisant les alias.
Reprenons l'exemple de la boutique en ligne du quiz. Voici des requêtes concrètes utilisant les jointures :
Cette technique utilise LEFT JOIN puis filtre sur WHERE c.id IS NULL pour ne garder que les clients sans commande correspondante.
Cette requête joint 4 tables pour afficher tous les détails d'une commande spécifique.
Les jointures peuvent devenir coûteuses sur de grandes tables. Voici quelques points clés :
Note : Les SGBD modernes optimisent automatiquement ces requêtes, mais il est bon de comprendre le principe.
En utilisant les tables utilisateurs et commandes présentées plus haut, écrivez une requête pour afficher tous les produits commandés par Alice.
Indice : Utilisez un INNER JOIN et une clause WHERE.
Écrivez une requête qui affiche le nom de tous les utilisateurs, ainsi que le nombre de commandes qu'ils ont passées (y compris 0 pour ceux qui n'ont jamais commandé).
Indice : Utilisez un LEFT JOIN avec COUNT() et GROUP BY.
Trouvez toutes les commandes qui n'ont pas d'utilisateur valide (comme la commande "Clavier" avec utilisateur_id = 4).
Indice : Utilisez un LEFT JOIN inversé ou un RIGHT JOIN avec WHERE ... IS NULL.
C'est indispensable pour la lisibilité, surtout quand vous joignez plus de deux tables.
Évitez SELECT * avec des jointures. Si deux tables ont une colonne avec le même nom (ex: id), cela peut créer une ambiguïté. Spécifiez toujours les colonnes que vous voulez en les préfixant avec leur alias : SELECT u.id, u.nom, c.id, c.produit.
Pour que les jointures sur de grandes tables soient rapides, assurez-vous que les colonnes utilisées dans la clause ON (généralement les clés étrangères) ont un index. (Nous verrons cela dans le module sur l'optimisation).