Combiner et empiler
INNER JOIN et LEFT JOIN relient deux tables par une clé commune. Mais une vraie analyse en croise souvent trois ou plus — et parfois on ne veut pas joindre, mais empiler des résultats ligne par ligne.
La troisième table
Les leçons précédentes ont croisé deux tables : films et realisateurs. Pour aller plus loin, une vraie analyse en croise souvent trois ou plus. L'univers cinéma dispose d'une troisième table naturelle : recompenses.
Table recompenses (fictive) — 5 distinctions attribuées à des films
| id | film_id | nom_prix | pays_ceremonie |
|---|---|---|---|
| 1 | 2 | Oscar du meilleur film | Américain |
| 2 | 4 | César du meilleur film | Français |
| 3 | 3 | Palme d'or | Français |
| 4 | 1 | BAFTA Meilleur film | Britannique |
| 5 | 2 | Palme d'or spéciale | Français |
La colonne film_id relie chaque récompense à son film — même principe que realisateur_id dans films. La condition ON sera donc recompenses.film_id = films.id. Le film id=2 (Le Parrain) apparaît deux fois : il a reçu deux récompenses distinctes.
JOIN sur 3 tables
Même syntaxe qu'avec INNER JOIN : on enchaîne un deuxième JOIN avec sa propre condition ON. Chaque JOIN ajoute une table et son lien — on peut en enchaîner autant que nécessaire.
Ici, deux enchaînements : films ↔ realisateurs (via realisateur_id), puis films ↔ recompenses (via film_id). Les deux conditions ON sont obligatoires.
SELECT f.titre AS film, r.nom AS realisateur, rec.nom_prix AS recompense
FROM films f
INNER JOIN realisateurs r ON f.realisateur_id = r.id
INNER JOIN recompenses rec ON rec.film_id = f.id
ORDER BY f.titre, rec.nom_prix| film | realisateur | recompense |
|---|---|---|
| Amélie Poulain | Jean-Pierre Jeunet | César du meilleur film |
| Inception | Christopher Nolan | BAFTA Meilleur film |
| Le Parrain | Francis Ford Coppola | Oscar du meilleur film |
| Le Parrain | Francis Ford Coppola | Palme d'or spéciale |
| Pulp Fiction | Quentin Tarantino | Palme d'or |
5 lignes au total. Le Parrain apparaît deux fois — il a reçu deux récompenses. JOIN renvoie une ligne par combinaison (film × récompense), pas une ligne par film. Fritz Lang (présent dans realisateurs mais sans film) n'apparaît pas — INNER JOIN l'exclut, comme la leçon précédente l'a montré.
UNION : empiler verticalement
La table recompenses et la table realisateurs stockent toutes deux une information d'origine géographique — pays_ceremonie (le pays où se tient la cérémonie) et nationalite (la nationalité du réalisateur). Pour lister toutes les origines représentées dans notre base, qu'elles correspondent à un réalisateur ou à une cérémonie, on ne joint pas ces tables : JOIN assemblerait des colonnes et mêlerait deux concepts distincts. On veut empiler les résultats verticalement. C'est le rôle de UNION.
UNION colle le résultat d'un SELECT sous un autre — c'est vertical, l'opposé de JOIN. Contrainte : les deux SELECT doivent avoir le même nombre de colonnes et des types compatibles. UNION supprime les doublons.
SELECT pays_ceremonie AS pays FROM recompenses
UNION
SELECT nationalite FROM realisateurs
ORDER BY pays| pays |
|---|
| Allemand |
| Américain |
| Britannique |
| Français |
pays_ceremonie et nationalite portent des noms différents dans leurs tables respectives. Le premier SELECT définit le nom de la colonne résultante — ici AS pays. Le second SELECT aligne ses valeurs sous ce libellé : le nombre et le type suffisent, les noms n'ont pas besoin d'être identiques. Américain et Français étaient présents dans les deux tables — UNION n'en garde qu'une occurrence chacun. Allemand vient uniquement de realisateurs (Fritz Lang, aucune cérémonie). ORDER BY se place après le dernier SELECT de l'UNION.
UNION ALL : empiler sans dédoublonner
UNION ALL se comporte comme UNION, mais garde toutes les lignes sans supprimer les doublons. La même paire de SELECT retourne 10 lignes au lieu de 4.
SELECT pays_ceremonie AS pays FROM recompenses
UNION ALL
SELECT nationalite FROM realisateurs
ORDER BY pays| pays |
|---|
| Allemand |
| Américain |
| Américain |
| Américain |
| Britannique |
| Britannique |
| Français |
| Français |
| Français |
| Français |
10 lignes au total (5 de recompenses + 5 de realisateurs). Américain apparaît 3 fois : une fois depuis recompenses (la cérémonie des Oscars) et deux fois depuis realisateurs (Coppola et Tarantino). Français apparaît 4 fois : trois fois depuis recompenses (Cannes × 2 + César) et une fois depuis realisateurs (Jeunet). UNION avec déduplication aurait retourné 4 lignes uniques. Utilise UNION ALL quand tu sais qu'il n'y a pas de doublon pertinent à supprimer, ou que tu veux les conserver — c'est aussi légèrement plus rapide (pas de déduplication).
JOIN + tout le reste
Un JOIN à 3 tables se combine avec tout ce que tu connais des leçons précédentes : WHERE, ORDER BY. Il n'y a pas de règle spéciale — ces outils s'appliquent normalement au résultat joint. Exemple concret : les films de réalisateurs américains avec leurs récompenses.
SELECT f.titre AS film, r.nom AS realisateur, rec.nom_prix AS recompense
FROM films f
INNER JOIN realisateurs r ON f.realisateur_id = r.id
INNER JOIN recompenses rec ON rec.film_id = f.id
WHERE r.nationalite = 'Américain'
ORDER BY f.titre, rec.nom_prix| film | realisateur | recompense |
|---|---|---|
| Le Parrain | Francis Ford Coppola | Oscar du meilleur film |
| Le Parrain | Francis Ford Coppola | Palme d'or spéciale |
| Pulp Fiction | Quentin Tarantino | Palme d'or |
WHERE filtre sur une colonne de realisateurs (la nationalité) alors que le résultat affiche des colonnes de trois tables différentes — exactement comme avec un JOIN à deux tables. Inception (Nolan = Britannique) et Amélie Poulain (Jeunet = Français) sont exclus par le WHERE. Le Parrain y apparaît deux fois car il a deux récompenses répertoriées.
Récapitulatif
Ce que tu retiens de cette leçon :
SELECT f.titre AS film, r.nom AS realisateur, rec.nom_prix AS recompenseFROM films f INNER JOIN realisateurs r ON f.realisateur_id = r.idINNER JOIN recompenses rec ON rec.film_id = f.id ORDER BY f.titre💡 Bon à savoir : JOIN et UNION répondent à des besoins différents — JOIN assemble des colonnes (horizontal), UNION empile des lignes (vertical). Tu peux enchaîner autant de JOIN que nécessaire, chacun avec sa propre condition ON.
Passe à la pratique
Cette leçon t'a montré la théorie. Pour maîtriser SQL, rien ne vaut la pratique : accède aux exercices et au bac à sable PostgreSQL réel.