Jointure interne vs jointure externe : lignes conservées, NULL, jointures gauche et droite, syntaxe SQL

Une jointure combine les lignes de deux tables selon la condition donnée dans ON (le plus souvent l’égalité d’une clé étrangère et d’une clé primaire) pour produire une seule table de résultat. Une jointure interne ne conserve que les combinaisons de lignes qui ont un partenaire correspondant ; les lignes sans partenaire disparaissent, dans les deux tables. Une jointure externe conserve les combinaisons correspondantes et aussi les lignes de la table désignée même sans partenaire, en remplissant les colonnes de l’autre table avec NULL. Une jointure externe gauche (LEFT OUTER JOIN) conserve toutes les lignes de la table de gauche, une jointure externe droite (RIGHT OUTER JOIN) celles de la table de droite, et une jointure externe complète (FULL OUTER JOIN) celles des deux. On choisit selon que les lignes sans partenaire doivent ou non apparaître dans le résultat.

CritèreJointure interne (INNER JOIN)Jointure externe (OUTER JOIN)
Lignes conservées dans le résultatSeulement les combinaisons de lignes qui satisfont la condition de jointureLes combinaisons correspondantes, plus les lignes sans partenaire de la table à conserver
Lignes sans correspondanceÉliminées du résultat, dans les deux tablesChaque ligne de la table conservée reste une fois, avec les colonnes de l’autre table à NULL ; les lignes sans correspondance de l’autre table sont éliminées
TypesUn seul type ; INNER peut être omis et l’on écrit simplement JOINTrois types : gauche (LEFT), droite (RIGHT) et complète (FULL) ; OUTER peut être omis
Exemple SQLSELECT … FROM employee INNER JOIN dept ON employee.dept_id = dept.dept_idSELECT … FROM employee LEFT OUTER JOIN dept ON employee.dept_id = dept.dept_id
Exemple de nombre de lignes (4 employés, dont un avec un identifiant de service NULL ; 3 services, dont un sans employé)3 lignes : l’employé dont l’identifiant de service est NULL et le service sans employé n’apparaissent pas4 lignes avec une jointure externe gauche qui conserve la table des employés (l’employé à l’identifiant de service NULL reçoit un nom de service NULL) ; 5 lignes avec une jointure externe complète qui conserve les deux
Ordre des tablesInverser gauche et droite donne les mêmes lignes (seul l’ordre des colonnes change)Pour les jointures externes gauche et droite, la table écrite à gauche change le résultat ; A LEFT OUTER JOIN B renvoie les mêmes lignes que B RIGHT OUTER JOIN A
Conditions sur les colonnes de l’autre tableMême résultat qu’elles soient écrites dans ON ou dans la clause WHEREÉcrites dans la clause WHERE, les lignes remplies de NULL ne satisfont pas la condition et disparaissent, ce qui peut donner le même résultat qu’une jointure interne ; il faut les écrire dans ON pour conserver les lignes sans correspondance
Usages typiquesLorsqu’on ne veut que les données présentes dans les deux tables (par exemple ajouter le nom du client aux commandes)Lorsqu’il faut aussi lister les lignes sans correspondance (par exemple tous les employés, y compris ceux sans service), ou pour rechercher les lignes sans partenaire

Les valeurs indiquées sont des ordres de grandeur typiques et varient selon la génération de procédé et le produit.

Quand choisir l'un ou l'autre ?

Jointure interne
À utiliser lorsqu’on n’a besoin que des lignes ayant des données correspondantes dans les deux tables. Par exemple, pour ajouter le nom du client à une liste de commandes quand les commandes au client inconnu ne sont pas utiles, on utilise une jointure interne.
Jointure externe
À utiliser lorsque les lignes sans partenaire ne doivent pas disparaître. Par exemple, pour ajouter le nom du service à la liste de tous les employés en conservant ceux qui n’ont pas de service, on utilise une jointure externe gauche qui conserve la table des employés. Une jointure externe permet aussi de trouver les lignes sans partenaire, comme les clients qui n’ont jamais commandé, en sélectionnant les lignes où la colonne de clé primaire de l’autre table est NULL.

Questions fréquentes

En quoi les jointures externes gauche et droite diffèrent-elles ?

Uniquement par la table dont toutes les lignes sont conservées. Une jointure externe gauche conserve les lignes de la table de gauche, écrite en premier dans FROM, même sans partenaire ; une jointure externe droite conserve celles de la table de droite, écrite en second. A LEFT OUTER JOIN B et B RIGHT OUTER JOIN A renvoient les mêmes lignes ; pour la lisibilité, on écrit donc souvent les requêtes uniformément avec des jointures externes gauches.

Pourquoi une jointure peut-elle renvoyer plus de lignes que les tables d’origine ?

Dans une jointure, chaque combinaison de lignes qui satisfait la condition devient une ligne du résultat. Lorsque la colonne de jointure contient des valeurs en double dans les deux tables, le nombre de combinaisons se multiplie. Par exemple, si une table a 2 lignes de valeur 1 et l’autre aussi 2, cette seule valeur donne 2 × 2 = 4 lignes.

Que se passe-t-il sans condition de jointure ?

Le résultat est l’ensemble de toutes les combinaisons de lignes des deux tables (le produit cartésien). C’est ce qu’on appelle un CROSS JOIN : une table de 4 lignes et une table de 3 lignes donnent 4 × 3 = 12 lignes. Produire un produit cartésien par erreur, par exemple en oubliant ON, fait exploser le nombre de lignes : il faut donc y prendre garde.

Les NULL se correspondent-ils dans une condition de jointure ?

Non. En SQL, une comparaison avec NULL n’est jamais vraie, donc des lignes dont les colonnes de jointure sont NULL dans les deux tables ne sont pas combinées. Par conséquent, une jointure interne élimine les lignes dont la colonne de jointure est NULL.

Vérifier vos connaissances

Une table Employe(NumEmploye, Nom, IdService) contient 4 lignes dont les valeurs IdService sont, dans l'ordre, 10, 20, 10 et NULL. Une table Service(IdService, NomService) contient 3 lignes dont IdService vaut 10, 20 et 30. Combien de lignes renvoie SELECT Employe.Nom, Service.NomService FROM Employe INNER JOIN Service ON Employe.IdService = Service.IdService ?

  1. A3 lignes
  2. B4 lignes
  3. C12 lignes
Afficher la réponse et l'explication

Réponse : A. 3 lignes

Une jointure interne (INNER JOIN) ne renvoie que les combinaisons de lignes qui satisfont la condition ON. Les 2 employés dont IdService vaut 10 se combinent avec le service 10, et l'employé dont IdService vaut 20 avec le service 20 ; le résultat compte donc 3 lignes. L'employé dont IdService est NULL n'est joint à aucun service, car une comparaison avec NULL n'est jamais vraie, et il disparaît du résultat. Le service 30, qui n'a aucun employé, n'apparaît pas non plus. 4 lignes correspond à une jointure externe gauche qui garde toutes les lignes de la table Employe (Employe LEFT OUTER JOIN Service). 12 lignes correspond au CROSS JOIN (produit cartésien), qui forme toutes les combinaisons sans condition : 4 × 3 = 12 lignes.

Une table Employe(NumEmploye, Nom, IdService) contient 5 lignes dont les valeurs IdService sont, dans l'ordre, 10, 20, 10, NULL et NULL. Une table Service(IdService, NomService) contient 3 lignes dont IdService vaut 10, 20 et 30. Combien de lignes renvoie SELECT Service.NomService, Employe.Nom FROM Service LEFT OUTER JOIN Employe ON Service.IdService = Employe.IdService ?

  1. A3 lignes
  2. B4 lignes
  3. C5 lignes
Afficher la réponse et l'explication

Réponse : B. 4 lignes

Une jointure externe gauche (LEFT OUTER JOIN) garde toutes les lignes de la table de gauche (ici la table Service) ; lorsque la table de droite n'a pas de ligne correspondante, elle produit une ligne dont les colonnes de la table de droite sont remplies de NULL. Le service 10 a 2 employés, ce qui donne 2 lignes ; le service 20 donne 1 ligne ; et le service 30, qui n'a aucun employé, donne 1 ligne avec un nom NULL, soit 4 lignes au total. Les 2 employés dont IdService est NULL ne correspondent à aucun service et, étant des lignes de la table de droite, qui n'est pas celle conservée intégralement, n'apparaissent pas dans le résultat. Une jointure interne éliminerait aussi la ligne du service 30, ce qui donnerait 3 lignes. Inverser les tables en Employe LEFT OUTER JOIN Service garde les 5 employés, ce qui donne 5 lignes. Avec les jointures externes, il est important de vérifier quelle table conserve toutes ses lignes.

La colonne x de la table R contient 4 lignes de valeurs 1, 1, 2, 3, et la colonne x de la table S contient 4 lignes de valeurs 1, 1, 2, 4. Combien de lignes renvoie SELECT * FROM R INNER JOIN S ON R.x = S.x ?

  1. A2 lignes
  2. B3 lignes
  3. C5 lignes
Afficher la réponse et l'explication

Réponse : C. 5 lignes

Dans une jointure, chaque combinaison de lignes qui satisfait la condition devient une ligne du résultat. Pour x = 1, toutes les combinaisons des 2 lignes de R et des 2 lignes de S satisfont la condition, ce qui donne 2 × 2 = 4 lignes ; pour x = 2, il y a 1 × 1 = 1 ligne. Le 3 de R et le 4 de S n'ont pas de partenaire et n'apparaissent donc pas dans la jointure interne. Le total est de 4 + 1 = 5 lignes. 2 lignes correspond au cas où l'on ne produirait qu'une ligne par valeur correspondante (1 et 2). 3 lignes correspond au cas où l'on vérifie seulement, pour chaque ligne de R, si S contient une valeur correspondante (une requête comme SELECT * FROM R WHERE x IN (SELECT x FROM S)). Le produit cartésien sans condition donnerait 4 × 4 = 16 lignes. Attention : des valeurs en double dans la colonne de jointure multiplient le nombre de lignes du résultat.

  1. À partir d'une table Client(IdClient, Nom) et d'une table Commande(IdCommande, IdClient, Montant), on veut obtenir le nom des clients qui n'ont jamais passé de commande. Quelle instruction SQL est correcte ?

Questions d'entraînement sur Bases des bases de données

Termes clés expliqués

SQL
Langage standard des bases de données relationnelles, qui sert à définir les tables, à rechercher, insérer, mettre à jour et supprimer des données, et à contrôler les privilèges. Il est normalisé par l'ISO/IEC (au Japon aussi sous forme de norme JIS). Ses instructions comprennent SELECT, INSERT, UPDATE, DELETE, CREATE TABLE et GRANT.
Base de données relationnelle
Base de données qui représente les données sous forme de tables (relations) de lignes et de colonnes, et relie les tables entre elles par des valeurs communes. On l'appelle aussi SGBDR ou RDB. Les requêtes et mises à jour se font en SQL, et des contraintes comme les clés primaires et les clés étrangères maintiennent la cohérence des données.
Clé primaire
Colonne, ou ensemble de colonnes, qui sert à identifier de façon unique une ligne d'une table. Elle est soumise aux contraintes selon lesquelles ses valeurs ne doivent pas comporter de doublons ni contenir de NULL. La clé primaire est choisie parmi les ensembles minimaux de colonnes capables d'identifier une ligne de façon unique (clés candidates).
Clé étrangère (foreign key)
Colonne qui fait référence à la clé primaire (ou à une colonne unique) d'une autre table. Grâce à la contrainte d'intégrité référentielle, qui n'admet que des valeurs existant dans la table référencée ou NULL, elle empêche les données qui pointent vers des lignes inexistantes. On peut aussi préciser le comportement lorsqu'une ligne référencée est supprimée ou mise à jour (refus, suppression en cascade, etc.).
Normalisation
Démarche de conception qui découpe les tables d'une base de données relationnelle en fonction des dépendances fonctionnelles entre colonnes, afin que le même fait ne soit pas enregistré à plusieurs endroits. Elle supprime les données en double et évite les anomalies de mise à jour, d'insertion et de suppression. Ses étapes comprennent les première à troisième formes normales et la forme normale de Boyce-Codd.
Vue (view)
Dans une base de données relationnelle, table virtuelle définie en donnant un nom à une instruction SELECT. Elle ne contient normalement aucune donnée propre et construit son résultat à partir des tables sous-jacentes à chaque fois qu'on y fait référence. Elle sert à simplifier des requêtes complexes et à restreindre l'accès en limitant les colonnes et les lignes affichées.

Comparatifs associés