INNER JOIN, la jointure de base
La leçon précédente t'a montré le lien entre tables. INNER JOIN t'apprend maintenant à l'exploiter : assembler les colonnes de deux tables en un seul résultat, en suivant la relation clé étrangère → clé primaire.
Quand un numéro ne suffit pas
Certaines colonnes stockent un identifiant numérique à la place d'une valeur lisible. C'est le cas de realisateur_id dans cette table films : le numéro 1 signifie Christopher Nolan, mais rien dans la table ne te le dit directement.
Table films (extrait, fictif) — avec realisateur_id
| titre | annee | realisateur_id |
|---|---|---|
| Inception | 2010 | 1 |
| Le Parrain | 1972 | 2 |
| Pulp Fiction | 1994 | 3 |
| Amélie Poulain | 2001 | 4 |
Pour afficher « Christopher Nolan » à côté d'Inception, il faut aller chercher l'information dans une deuxième table — realisateurs — qui fait correspondre les identifiants à leurs noms. C'est ce que fait INNER JOIN : lire dans les deux tables simultanément et assembler leurs colonnes dans un seul résultat.
La condition ON : le cœur du JOIN
La syntaxe d'INNER JOIN suit toujours le même schéma : FROM table1 INNER JOIN table2 ON condition. La condition dit comment les deux tables se correspondent — ici, l'identifiant du réalisateur dans films doit être égal à l'identifiant dans realisateurs.
Pour chaque ligne de films, PostgreSQL cherche dans realisateurs la ligne dont l'id correspond au realisateur_id du film. Les colonnes des deux lignes sont fusionnées en une seule ligne de résultat.
Table realisateurs (fictive — illustre le concept)
| id | nom | nationalite |
|---|---|---|
| 1 | Christopher Nolan | Britannique |
| 2 | Francis Ford Coppola | Américain |
| 3 | Quentin Tarantino | Américain |
| 4 | Jean-Pierre Jeunet | Français |
| 5 | Fritz Lang | Allemand |
SELECT films.titre, realisateurs.nom AS realisateur
FROM films
INNER JOIN realisateurs ON films.realisateur_id = realisateurs.id| titre | realisateur |
|---|---|
| Inception | Christopher Nolan |
| Le Parrain | Francis Ford Coppola |
| Pulp Fiction | Quentin Tarantino |
| Amélie Poulain | Jean-Pierre Jeunet |
4 lignes — un film par ligne, chacun avec le nom de son réalisateur. Fritz Lang (id 5 dans realisateurs) est absent : il n'a aucun film dans notre table films. INNER JOIN ne garde que les lignes qui trouvent une correspondance des deux côtés. Sans la clause ON, PostgreSQL renvoie une erreur de syntaxe — ON est obligatoire.
Préfixer : de quelle table vient cette colonne ?
Les deux tables ont toutes les deux une colonne qui s'appelle id. Si tu écris SELECT id, titre FROM films INNER JOIN realisateurs ON ..., PostgreSQL ne sait pas de laquelle tu parles et renvoie une erreur : column reference "id" is ambiguous.
Le préfixe résout l'ambiguïté : films.id désigne l'identifiant du film, et realisateurs.id celui du réalisateur. La requête de la section précédente applique déjà ce principe en écrivant films.titre et realisateurs.nom.
Même quand les noms de colonnes diffèrent — titre dans films, nom dans realisateurs — on garde les préfixes par convention. Ça rend immédiatement clair de quelle table vient chaque colonne, surtout dans une requête qui joint plusieurs tables.
Les alias de table : écrire moins, lire plus
Écrire films. et realisateurs. à chaque colonne et dans la condition ON alourdit rapidement la requête. La solution : déclarer un alias pour chaque table, juste après son nom dans le FROM.
FROM films f déclare que, pour toute la requête, f désigne films. On peut alors écrire f.titre, f.realisateur_id… au lieu de films.titre, films.realisateur_id. Ce style à une ou deux lettres est la convention universelle dans les bases professionnelles.
SELECT f.titre, r.nom AS realisateur
FROM films f
INNER JOIN realisateurs r ON f.realisateur_id = r.id| titre | realisateur |
|---|---|
| Inception | Christopher Nolan |
| Le Parrain | Francis Ford Coppola |
| Pulp Fiction | Quentin Tarantino |
| Amélie Poulain | Jean-Pierre Jeunet |
Le résultat est identique — seul le style de la requête change. f = films, r = realisateurs.
JOIN + WHERE + ORDER BY
Une fois les deux tables jointes, tous les outils des parcours précédents s'appliquent normalement au résultat combiné. WHERE filtre les lignes, ORDER BY les trie — exactement comme sur une table simple.
Tu peux filtrer ou trier sur une colonne de n'importe quelle table jointe. Ici, WHERE r.nationalite = 'Américain' filtre sur un champ de realisateurs, alors que le résultat affiche aussi des colonnes de films.
SELECT f.titre, r.nom AS realisateur, r.nationalite
FROM films f
INNER JOIN realisateurs r ON f.realisateur_id = r.id
WHERE r.nationalite = 'Américain'
ORDER BY f.annee| titre | realisateur | nationalite |
|---|---|---|
| Le Parrain | Francis Ford Coppola | Américain |
| Pulp Fiction | Quentin Tarantino | Américain |
WHERE et ORDER BY peuvent porter sur n'importe quelle colonne de n'importe quelle table jointe — pas seulement sur la table principale du FROM.
Récapitulatif
Ce que tu retiens de cette leçon :
SELECT f.titre, r.nom AS realisateurFROM films f INNER JOIN realisateurs r ON f.realisateur_id = r.id💡 Bon à savoir : INNER JOIN ne garde que les lignes qui ont une correspondance dans les deux tables. Fritz Lang — présent dans realisateurs mais sans film dans films — n'apparaît pas. C'est précisément ce que LEFT JOIN corrige : il affiche aussi les lignes sans correspondance. Ça arrive dans la leçon suivante.
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.