SQL : Jointures

Nous avons vu en algèbre relationnelle ce qu'étaient les jointures. Nous allons nous pencher ici sur leur application en SQL.

Exemples de jointure

Nous pouvons nous passer des opérateurs JOIN, et utiliser des SELECT imbriqués. Par exemple, pour trouver le numéro des élèves de sexe féminin qui ont suivi le cours de gymnastique de Mr Mégot, nous pouvons effectuer la requête suivante :


Code SQL (Requête 1) (3 lignes) :
  1. SELECT DISTINCT s.student_id FROM t_student s, t_course c
  2. WHERE s.gender='F'
  3. AND c.teacher_fk = (SELECT teacher_id FROM t_teacher WHERE UPPER(teacher_lastname) = 'MEGOT');

Ce type de requête était fort utilisé auparavant. Parfois, nous retrouvons même plusieurs requêtes exécutées à la suite dans une transaction.

Il est possible d'optimiser nettement notre requête par l'utilisation des jointures :

  1. SELECT DISTINCT s.student_id FROM t_student s, t_course c
  2. WHERE
  3. s.student_id = c.student_fk /* jointure entre t_student et t_course */
  4. AND c.teacher_fk = teacher_id /* jointure entre t_course et t_teacher */
  5. AND s.gender='F'
  6. AND UPPER(teacher_lastname) = 'MEGOT');

Il est possible de rendre cette requête beaucoup plus lisible :


Code SQL (Requête 2b) (5 lignes) :
  1. SELECT DISTINCT s.student_id FROM
  2. ( t_student s INNER JOIN course c ON s.student_id = c.student_fk )
  3. INNER JOIN t_teacher t ON t.teacher_id = c.teacher_fk
  4. WHERE s.gender='F'
  5. AND UPPER(teacher_lastname) = 'MEGOT';

Une jointure permet d'associer des colonnes de tables différentes pour étendre le champ des recherches, pour peu que chaque table contienne un champ dont les valeurs correspondent à celles d'une autre table. Dans le cadre de notre exemple, les valeurs du champ student_fk de la table t_course correspondent à des valeurs du champ student_id de la table t_student.

Remarque

Une jointure naturelle, ce peut sembler beaucoup plus lisible car les deux champs portent le même nom (par exemple t_student.student_id et t_course.student_id), mais la jointure fonctionne parfaitement même si les noms des champs sont différents (equi-jointure dans notre exemple, avec t_student.student_id et t_course.student_fk).

Pour ma part, je préfère utiliser le suffixe _fk qui permet de savoir facilement que nous sommes en présence d'un champs qui fait référence à une autre table (et qui est donc soumis à une contrainte de type Foreign key).

Autres types de jointures

Nous pouvons aussi trouver d'autres types de jointures :

  • Auto-jointure : jointure d'une table avec elle même dans le cas par exemple d'un système hiérarchique (un champ de la table référence un autre champ de cette même table).
  • Jointure hétérogène : jointure entre plusieurs bases de données.
  • Jointure externe : jointure qui permet de retourner une table sans concordance.
  • Jointure croisée : jointure qui retourne le produit cartésien de plusieurs tables.

 

INNER JOIN

Un INNER JOIN est le type de jointure par défaut, qui retourne les enregistrements dont les valeurs comparées sont égales.

Nous pouvons représenter la jointure INNER JOIN par le schéma suivant :

INNER JOIN

Nous pouvons par exemple demander le nom et prénom des étudiants qui ont suivi un cours, ainsi que les dates et intitulés des cours suivis :


Code SQL (Exemple d'INNER JOIN) (2 lignes) :
  1. SELECT s.student_lastname, s.student_firstname, c.course_start_date, c.course_name FROM
  2. t_student s INNER JOIN course c ON s.student_id = c.student_fk;
  • Nous n'avons pas la totalité des élèves, car ceux qui n'ont pas suivi de cours n'apparaissent pas.
  • Nous n'avons pas la totalité des cours, car nous n'avons pas les cours qui n'ont pas d'élèves (cours qui n'ont pas encore été donnés).

 

LEFT JOIN

La jointure LEFT JOIN nous permet non seulement de demander les enregistrements dont les valeurs comparées sont égales, mais aussi la totalité des enregistrements de la table de gauche.

Nous pouvons représenter la jointure LEFT JOIN par le schéma suivant :

LEFT JOIN

Nous pouvons demander tous les noms des élèves ainsi que les dates et intitulés des cours suivis par certains de ces élèves :


Code SQL (Exemple de LEFT JOIN) (2 lignes) :
  1. SELECT s.student_lastname, s.student_firstname, c.course_start_date, c.course_name FROM
  2. t_student s LEFT JOIN course c ON s.student_id = c.student_fk;

Cette requête différe seulement d'un mot par rapport à la précédente. En spécifiant que la requête comporte une jointure de type LEFT JOIN au lieu d'INNER JOIN, nous pouvons constater les effets suivants :

  • Nous avons la totalité des élèves, même ceux qui n'ont suivi aucun cours (aucune correspondance avec la table cours).
  • Nous n'avons pas la totalité des cours, car nous n'avons pas les cours qui n'ont pas d'élèves.

 

RIGHT JOIN

La jointure RIGHT JOIN repose sur le même principe que la jointure LEFT JOIN, mais c'est la totalité des enregistrements de la table de droite qui est retournée en plus des éléments qui satisfont à l'égalité.

RIGHT JOIN

Nous pouvons demander tous les noms des élèves qui ont suivi au moins un cours, et l'ensemble des dates et intitulés de tous les cours :


Code SQL (Exemple de RIGHT JOIN) (2 lignes) :
  1. SELECT s.student_lastname, s.student_firstname, c.course_start_date, c.course_name FROM
  2. t_student s RIGHT JOIN course c ON s.student_id = c.student_fk;
  • Nous avons seulement les élèves qui ont suivi au moins un cours.
  • Nous avons la totalité des cours, y compris ceux qui n'ont été donnés à aucun de ces élèves.

JOIN et les SGBD

Les jointures sont vivement conseillées, mais nous devons préalablement vérifier que la base de données supporte ce type de requête. Voici un petit résumé de la situation :

  • Oracle : depuis la version 9.
  • MySQL :
    • INNER JOIN depuis la version 3.23.17
    • UNION et CROSS JOIN depuis la version 4.0.11
  • PostGreSQL : LEFT et RIGHT seulement.
  • DB2 : LEFT seulement

Depuis la création de ce document, la prise en charge de ces opérateurs par les SGBD cités est peut-être plus étendue.

 

Document créé le 17/03/07 22:02, dernière modification le 14/07/17 17:21
Source du document imprimé : https://www.gaudry.be/sql-join.html

L'infobrol est un site personnel dont le contenu n'engage que moi. Le texte est mis à disposition sous licence CreativeCommons(BY-NC-SA). Plus d'info sur les conditions d'utilisation et sur l'auteur.