CodeGym /Cours /SQL SELF /Conditions supplémentaires dans JOIN : ON ... AND ...

Conditions supplémentaires dans JOIN : ON ... AND ...

SQL SELF
Niveau 12, Leçon 2
Disponible

Tu sais déjà comment joindre des tables avec JOIN. Mais dans la vraie vie, un simple match sur les clés ne suffit pas toujours. Souvent, il faut joindre les données seulement si elles remplissent un critère en plus — genre, seulement les lignes actives, ou juste les données de l'année en cours, ou uniquement les commandes terminées.

Et c'est là que l'extension de la clause ON avec AND entre en jeu.

Les conditions supplémentaires dans JOIN ... ON te permettent de contrôler précisément quelles lignes participent à la jointure, avant même que SQL commence à construire le résultat. Ça rend la requête :

  • Plus rapide (moins de lignes passent par le JOIN),
  • Plus précise (le filtrage se fait au moment de la jointure),
  • Plus prévisible avec un LEFT JOIN (contrairement au filtrage dans WHERE).

Exemple : Uniquement les inscriptions actives aux cours

Imaginons que la table enrollments contient le statut de participation de l'étudiant : active, dropped, pending.

Table students :

id nom
1 Otto Song
2 Maria Chi
3 Alex Lin

Table enrollments mise à jour :

student_id course_id statut
1 101 active
1 103 active
2 102 dropped
3 101 active

Table courses :

id nom
101 Mathématiques
102 Physique
103 Informatique

Maintenant, on veut récupérer seulement les étudiants qui ont des cours actifs :

SELECT 
    students.name AS student_name,
    courses.name AS course_name
FROM students 
INNER JOIN enrollments 
    ON students.id = enrollments.student_id
    AND enrollments.status = 'active'
INNER JOIN courses 
    ON enrollments.course_id = courses.id;

Résultat :

student_name course_name
Otto Song Mathématiques
Otto Song Informatique
Alex Lin Mathématiques

Ici, on a ajouté AND enrollments.status = 'active' dans le ON, pour que la jointure se fasse uniquement sur les lignes actives, et pas en filtrant après la jointure.

Pourquoi pas WHERE ?

On aurait pu écrire comme ça :

...
WHERE enrollments.status = 'active'

Mais ça ne se comporte pas pareil avec un LEFT JOIN. Le filtrage dans WHERE enlève les lignes où il n'y a pas de match (NULL), et du coup transforme ton LEFT JOIN en INNER JOIN.

Alors que la condition AND enrollments.status = 'active' dans le ON limite direct les lignes à joindre — ça contrôle quelles lignes vont dans la jointure, pas juste le résultat final.

Cette approche est super importante si tu veux garder les lignes d'une table même si y'a rien en face dans l'autre table (ce qui arrive souvent dans les rapports et l'analytics).

Encore des exemples avec ON ... AND ...

Table students :

id nom
1 Otto Song
2 Maria Chi
3 Alex Lin

Table enrollments :

student_id course_id statut enrolled_at
1 101 active 2025-02-01
1 103 active 2025-03-05
2 102 dropped 2024-05-15
3 101 active 2025-03-12

Table courses :

id nom
101 Math
102 Physique
103 CS

Exemple : uniquement les cours de l'année en cours

SELECT
    students.name,
    courses.name,
    enrollments.enrolled_at
FROM students
JOIN enrollments
    ON students.id = enrollments.student_id
    AND EXTRACT(YEAR FROM enrollments.enrolled_at) = EXTRACT(YEAR FROM CURRENT_DATE)
JOIN courses
    ON enrollments.course_id = courses.id;

Ici, on ne joint que les lignes qui concernent l'année en cours.

nom nom enrolled_at
Otto Song Math 2025-02-01
Otto Song CS 2025-03-05
Alex Lin Math 2025-03-12

Exemple : exclusion par valeur

JOIN enrollments
    ON students.id = enrollments.student_id
    AND enrollments.status != 'dropped'

On exclut les étudiants qui ont abandonné au moment de la jointure, pas après.

nom nom
Otto Song Math
Otto Song CS
Alex Lin Math

Quand la condition est dans le ON, PostgreSQL peut optimiser le plan de jointure et traiter moins de lignes. C'est super important sur de gros volumes de données. Le filtrage interne est plus efficace que de "jeter" après le JOIN.

JOIN ON — c'est pas que pour les clés

Beaucoup pensent que ON c'est juste id = id. En vrai, tu peux mettre dedans :

  • Opérateurs logiques : AND, OR, NOT
  • Comparaisons : >, <, <>, BETWEEN, IN
  • Expressions : EXTRACT, DATE_TRUNC, COALESCE, NULLIF

On combine tout ensemble

Table students :

id nom
1 Otto Song
2 Maria Chi
3 Alex Lin

Table faculties :

id nom
10 Ingénierie
20 Sciences naturelles
30 ← sans nom (NULL)

Table courses :

id nom enseignant faculty_id
101 Math Liam Park 10
102 Physique Chloe Zhang 20
103 CS Noah Kim 10
104 EPS Ava Chen 30

Table enrollments :

student_id course_id statut
1 101 active
1 103 active
2 102 dropped
3 101 active
3 104 active
SELECT
    s.name AS student_name,
    c.name AS course_name,
    f.name AS faculty_name
FROM students s
JOIN enrollments e
    ON s.id = e.student_id
    AND e.status = 'active'
JOIN courses c
    ON e.course_id = c.id
    AND c.name != 'EPS'
JOIN faculties f
    ON c.faculty_id = f.id
    AND f.name IS NOT NULL;

Ici, on filtre en même temps sur :

  • Les lignes actives,
  • Les cours sauf "EPS",
  • Les facultés qui ont un nom.

Résultat de la requête :

student_name course_name faculty_name
Otto Song Math Ingénierie
Otto Song CS Ingénierie
Alex Lin Math Ingénierie

J'espère que t'as kiffé cette leçon. Tu vas utiliser super souvent plusieurs JOIN avec des filtres dans tes requêtes. Presque tout le temps :)

2
Mission
SQL SELF, niveau 12, leçon 2
Bloqué
Sélectionner les étudiants avec des cours actifs
Sélectionner les étudiants avec des cours actifs
2
Mission
SQL SELF, niveau 12, leçon 2
Bloqué
Sélection des enregistrements pour l'année en cours
Sélection des enregistrements pour l'année en cours
Commentaires
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION