Les jointures SQL sont le fondement des bases de données relationnelles. Elles vous permettent de combiner des données de deux ou plusieurs tables basées sur des colonnes liées. Ce guide utilise des diagrammes visuels et des exemples pratiques pour clarifier chaque type de jointure.
Données d'exemple : Nos deux tables
Dans ce guide, nous utiliserons ces deux tables simples :
-- employees table
+----+----------+---------------+
| id | name | department_id |
+----+----------+---------------+
| 1 | Alice | 1 |
| 2 | Bob | 2 |
| 3 | Charlie | 1 |
| 4 | Diana | NULL |
+----+----------+---------------+
-- departments table
+----+-------------+
| id | dept_name |
+----+-------------+
| 1 | Engineering |
| 2 | Marketing |
| 3 | Sales |
+----+-------------+INNER JOIN (Jointure interne)
Retourne uniquement les lignes qui ont des valeurs correspondantes dans les deux tables. C'est l'intersection de deux ensembles.
Table A Table B
+---------+ +---------+
| | | |
| +----+-----+----+ |
| | INNER JOIN | |
| +----+-----+----+ |
| | | |
+---------+ +---------+SELECT e.name, d.dept_name
FROM employees e
INNER JOIN departments d ON e.department_id = d.id;Résultat:
+----------+-------------+
| name | dept_name |
+----------+-------------+
| Alice | Engineering |
| Bob | Marketing |
| Charlie | Engineering |
+----------+-------------+
-- Diana excluded (department_id is NULL)
-- Sales excluded (no employee in Sales)Utilisez quand vous ne voulez que les enregistrements existant dans les deux tables.
LEFT JOIN (Jointure externe gauche)
Retourne toutes les lignes de la table gauche et les lignes correspondantes de la table droite. Sans correspondance, les colonnes droites sont NULL.
Table A Table B
+---------+ +---------+
|XXXXXXXXX| | |
|XXXX+----+-----+----+ |
|XXXX| LEFT JOIN XXXX| |
|XXXX+----+-----+----+ |
|XXXXXXXXX| | |
+---------+ +---------+
(all of A + matching B)SELECT e.name, d.dept_name
FROM employees e
LEFT JOIN departments d ON e.department_id = d.id;Résultat:
+----------+-------------+
| name | dept_name |
+----------+-------------+
| Alice | Engineering |
| Bob | Marketing |
| Charlie | Engineering |
| Diana | NULL |
+----------+-------------+
-- Diana included with NULL dept_nameUtilisez quand vous avez besoin de tous les enregistrements de la table gauche.
RIGHT JOIN (Jointure externe droite)
Retourne toutes les lignes de la table droite et les lignes correspondantes de la table gauche.
Table A Table B
+---------+ +---------+
| | |XXXXXXXXX|
| +----+-----+XXXX+XXXX|
| |XXXX RIGHT JOINXXXX|
| +----+-----+XXXX+XXXX|
| | |XXXXXXXXX|
+---------+ +---------+
(matching A + all of B)SELECT e.name, d.dept_name
FROM employees e
RIGHT JOIN departments d ON e.department_id = d.id;Résultat:
+----------+-------------+
| name | dept_name |
+----------+-------------+
| Alice | Engineering |
| Charlie | Engineering |
| Bob | Marketing |
| NULL | Sales |
+----------+-------------+
-- Sales included with NULL nameUtilisez quand vous avez besoin de tous les enregistrements de la table droite.
FULL OUTER JOIN (Jointure externe complète)
Retourne toutes les lignes des deux tables. Les valeurs manquantes sont remplies avec NULL.
Table A Table B
+---------+ +---------+
|XXXXXXXXX| |XXXXXXXXX|
|XXXX+----+-----+XXXX+XXXX|
|XXXX|FULL OUTER JOINXXXX|
|XXXX+----+-----+XXXX+XXXX|
|XXXXXXXXX| |XXXXXXXXX|
+---------+ +---------+
(everything from both)SELECT e.name, d.dept_name
FROM employees e
FULL OUTER JOIN departments d ON e.department_id = d.id;Résultat:
+----------+-------------+
| name | dept_name |
+----------+-------------+
| Alice | Engineering |
| Bob | Marketing |
| Charlie | Engineering |
| Diana | NULL |
| NULL | Sales |
+----------+-------------+Utilisez quand vous avez besoin de tous les enregistrements des deux tables.
CROSS JOIN (Jointure croisée)
Retourne le produit cartésien des deux tables. Pas de clause ON nécessaire.
SELECT e.name, d.dept_name
FROM employees e
CROSS JOIN departments d;
-- Returns 4 × 3 = 12 rowsRésultat:
+----------+-------------+
| name | dept_name |
+----------+-------------+
| Alice | Engineering |
| Alice | Marketing |
| Alice | Sales |
| Bob | Engineering |
| Bob | Marketing |
| Bob | Sales |
| Charlie | Engineering |
| Charlie | Marketing |
| Charlie | Sales |
| Diana | Engineering |
| Diana | Marketing |
| Diana | Sales |
+----------+-------------+Utilisez pour générer des combinaisons ou des données de test.
Auto-jointure (Self JOIN)
Une table jointe avec elle-même. Utile pour les données hiérarchiques.
-- employees_v2 with manager_id column
+----+---------+------------+
| id | name | manager_id |
+----+---------+------------+
| 1 | Alice | NULL |
| 2 | Bob | 1 |
| 3 | Charlie | 1 |
| 4 | Diana | 2 |
+----+---------+------------+
SELECT
e.name AS employee,
m.name AS manager
FROM employees_v2 e
LEFT JOIN employees_v2 m ON e.manager_id = m.id;Résultat:
+----------+---------+
| employee | manager |
+----------+---------+
| Alice | NULL |
| Bob | Alice |
| Charlie | Alice |
| Diana | Bob |
+----------+---------+Utilisez pour les relations employé-manager ou les catégories hiérarchiques.
Quelle jointure utiliser ? Référence rapide
| Type de jointure | Retourne | Cas d'utilisation |
|---|---|---|
| INNER JOIN | A ∩ B | Only matching data |
| LEFT JOIN | A + (A ∩ B) | All left + matching right |
| RIGHT JOIN | (A ∩ B) + B | All right + matching left |
| FULL OUTER JOIN | A ∪ B | Everything from both |
| CROSS JOIN | A × B | Generate all combinations |
| Self JOIN | Depends on join type | Hierarchical / self-referencing data |
Conseils de performance
- Indexez toujours vos colonnes de JOIN.
- Évitez SELECT * en production.
- Placez la plus petite table en premier dans FROM.
- Utilisez EXPLAIN ANALYZE pour inspecter le plan d'exécution.
- Préférez EXISTS à IN pour les sous-requêtes corrélées.
- Évitez les jointures sur des expressions ou fonctions.
-- Create index on JOIN column
CREATE INDEX idx_emp_dept ON employees(department_id);
-- Use EXPLAIN to check query plan
EXPLAIN ANALYZE
SELECT e.name, d.dept_name
FROM employees e
INNER JOIN departments d ON e.department_id = d.id;Erreurs courantes
| Erreur | Problème | Solution |
|---|---|---|
| Using SELECT * | Returns unnecessary columns, wastes bandwidth | Select only needed columns |
| Missing index on JOIN column | Full table scan, extremely slow | CREATE INDEX |
| NULL comparison trap | NULL = NULL evaluates to FALSE | Use IS NULL or COALESCE |
| Accidental Cartesian product | Missing ON condition, row explosion | Always verify ON clause |
| Filtering OUTER JOIN in WHERE | WHERE filter turns LEFT JOIN into INNER JOIN | Put conditions in ON clause |
| Unnecessary DISTINCT | Hides incorrect JOIN logic | Fix JOIN condition, don't add DISTINCT |
| Joining on functions | Index unusable, forces full scan | Store normalized data or use computed columns |
-- ❌ Wrong: WHERE turns LEFT JOIN into INNER JOIN
SELECT e.name, d.dept_name
FROM employees e
LEFT JOIN departments d ON e.department_id = d.id
WHERE d.dept_name = 'Engineering'; -- filters out NULLs!
-- ✅ Correct: Put condition in ON clause
SELECT e.name, d.dept_name
FROM employees e
LEFT JOIN departments d
ON e.department_id = d.id
AND d.dept_name = 'Engineering'; -- preserves NULLsQuestions fréquemment posées
Quelle est la différence entre INNER JOIN et OUTER JOIN ?
INNER JOIN retourne uniquement les lignes correspondantes. OUTER JOIN inclut aussi les lignes non correspondantes avec des NULL.
Peut-on joindre plus de deux tables ?
Oui. Vous pouvez chaîner plusieurs JOINs sans limite pratique.
Que se passe-t-il si j'oublie la clause ON ?
Dans la plupart des dialectes SQL, cela provoque une erreur de syntaxe.
LEFT JOIN et LEFT OUTER JOIN sont-ils identiques ?
Oui. Le mot-clé OUTER est optionnel.
Quelle jointure est la plus rapide ?
INNER JOIN est généralement la plus rapide. La performance réelle dépend des index et de l'optimiseur.
Qu'est-ce qu'un NATURAL JOIN ?
Un NATURAL JOIN joint automatiquement sur les colonnes de même nom. Déconseillé en production.