Retour à la liste des articles Articles
7 minutes de lecture

Comment conserver les lignes non appariées de deux tables dans une jointure SQL ?

Cherchez-vous à joindre deux tables en SQL sans supprimer les lignes non appariées ? Voulez-vous conserver les lignes non appariées d'une ou des deux tables ? Dans cet article, je vais vous expliquer comment conserver tous les enregistrements que vous souhaitez en utilisant les jointures externes, telles que LEFT JOIN, RIGHT JOIN et FULL JOIN. Exemples inclus !

Le SQL JOIN est un outil puissant qui vous aide à combiner les données de plusieurs tables de votre base de données. Il s'agit d'une idée centrale des bases de données relationnelles : stocker des données dans différentes tables liées entre elles et combiner les données de ces tables lorsque cela est nécessaire pour l'analyse des données et la création de rapports. Si vous avez besoin d'un récapitulatif sur la jonction de tables en SQL, consultez ce guide pour débutants et notre cours interactif Les jointures en SQL cours interactif.

Malheureusement, lorsque vous débutez avec SQL, les requêtes JOIN peuvent produire des résultats frustrants. Par exemple, vous pouvez obtenir des doublons, des données manquantes, des valeurs NULL inattendues, etc. Dans cet article, je veux me concentrer sur le cas où vous voulez conserver des lignes non appariées de deux tables mais où un JOIN SQL les supprime. Nous allons voir pourquoi cela se produit et comment obtenir le résultat que vous attendez.

Commençons par un exemple.

Supposons que vous planifiez une campagne de marketing dans laquelle vous offrez un bonus spécial à un ensemble de vos clients. Il existe plusieurs critères pour qu'un client puisse bénéficier de ce bonus. Pour cette campagne particulière, vous recherchez des clients dont les commandes ont le statut "Terminé" depuis le mois dernier, mais qui n'ont pas gagné lors de votre précédente campagne de marketing.

Vous souhaitez combiner les informations des trois tables suivantes :

customers
idfirst_namelast_nameemail
101KateWilsonkate101@gmail.com
102MariaWhitemaria102@gmail.com
103JohnSmithjohn103@gmail.com
104PhilipStevensphilip104@gmail.com

orders
idorder_datecustomer_idstaff_idorder_status
102022-01-19102301Completed
112022-01-20104301Completed
122022-01-25101304Completed
132022-01-31110302Completed

last_campaign_participants
campaign_idcustomer_idwinner
222104True
222101False
222110False

Vous pouvez utiliser la requête suivante pour joindre ces tables et obtenir une liste de clients avec les informations supplémentaires dont vous avez besoin :

SELECT 
  c.id, 
  c.first_name, 
  c.last_name, 
  o.order_status, 
  lcp.winner
FROM customers c
JOIN orders o
ON c.id = o.customer_id
JOIN last_campaign_participants lcp
ON c.id = lcp.customer_id;

Si vous n'êtes pas sûr du fonctionnement de cette requête, consultez notre cours interactif avec 93 défis de codage couvrant différents types de JOINs.

Voici le résultat de la requête SQL ci-dessus :

idfirst_namelast_nameorder_statuswinner
101KateWilsonCompletedfalse
104PhilipStevensCompletedtrue

Comme vous le voyez, le résultat ne comprend que deux clients sur quatre. En effet, seuls ces deux clients ont des enregistrements correspondants dans les trois tables, et JOIN ou INNER JOIN ne produit que les lignes correspondantes. Avec cette sortie, nous ne voyons qu'un seul client éligible pour la prochaine campagne - Kate Wilson (ID 101). L'autre était le gagnant de notre dernière campagne et n'est donc pas éligible pour cette campagne.

Mais pouvons-nous manquer quelqu'un en supprimant les lignes non appariées ? En fait, oui. Nous pouvons ignorer des clients qui ont passé des commandes mais qui n'ont pas du tout participé à la dernière campagne. Ces clients sont absents de ce tableau. Nous voulons tous les clients dans la sortie de la jointure SQL, puis filtrer les résultats si nécessaire.

Heureusement, SQL dispose de jointures externes qui vous permettent de conserver les lignes non correspondantes de deux tables.

JOINs internes et JOINs externes

Contrairement à INNER JOIN, ou simplement JOIN, qui renvoie uniquement les lignes appariées de deux tables, les jointures externes renvoient également les lignes non appariées en SQL. Il existe plusieurs types de jointures externes :

  • Une LEFT JOIN renvoie tous les enregistrements de la table de gauche (première) même s'il n'y a pas de correspondance dans la table de droite (deuxième).
  • Une RIGHT JOIN renvoie tous les enregistrements de la (deuxième) table de droite, même s'il n'y a pas de correspondance dans la (première) table de gauche.
  • Une FULL JOIN renvoie tous les enregistrements des deux tables, y compris ceux qui ne correspondent à aucune des deux tables.

Cet article explique ces types de jointures SQL plus en détail à l'aide d'exemples et d'illustrations. Vous pouvez également consulter l'excellent aide-mémoireLes jointures en SQL pour connaître toutes les nuances de la syntaxe.

Pour utiliser une jointure externe, il suffit de remplacer le mot-clé JOIN par le mot-clé LEFT JOIN, RIGHT JOIN, ou FULL JOIN, selon le cas. Notez toutefois que pour LEFT JOIN et RIGHT JOIN, l'ordre des tables dans la requête SQL est important.

Modifions maintenant notre première requête pour conserver les lignes non appariées et obtenir tous les clients dans le résultat. Une option consiste à utiliser LEFT JOIN en s'assurant que la table customers figure en premier dans la requête (c'est-à-dire juste après le mot-clé FROM ) :

SELECT 
  c.id, 
  c.first_name, 
  c.last_name, 
  o.order_status, 
  lcp.winner
FROM customers c
LEFT JOIN orders o
ON c.id = o.customer_id
LEFT JOIN last_campaign_participants lcp
ON c.id = lcp.customer_id;

Le résultat de cette requête comprend une liste de tous les clients actuels avec les informations supplémentaires correspondantes provenant des deux autres tables. Notez que si aucun enregistrement ne correspond au client de la table de gauche, ces enregistrements sont tout de même inclus mais avec les valeurs NULL dans les colonnes respectives :

idfirst_namelast_nameorder_statuswinner
101KateWilsonCompletedfalse
102MariaWhiteCompletedNULL
103JohnSmithNULLNULL
104PhilipStevensCompletedtrue

En conservant les lignes non appariées avec une valeur LEFT JOIN, nous repérons un autre client qui peut bénéficier de la campagne. Plus précisément, Maria White (ID 102) a terminé ses commandes et n'a pas participé à la dernière campagne - elle n'a donc évidemment pas gagné.

Pour mieux comprendre les jointures externes, voyons quelques autres exemples.

Exemples de JOIN externes

Imaginons maintenant que nous gérons une librairie. Nous voulons comparer deux groupes de clients : ceux qui ont acheté Harry Potter et la pierre philosophale et ceux qui ont acheté Harry Potter et la chambre des secrets. S'agit-il des mêmes personnes ? Y a-t-il quelqu'un qui a acheté un livre mais pas l'autre ? Nous pourrions leur recommander l'autre livre.

philosophers_stone
product_idcustomer_idfirst_namelast_name
11301AndyBernard
11303RobertCalifornia
11305PamBeesley
11306OscarMartinez

chamber_of_secrets
product_idcustomer_idfirst_namelast_name
12301AndyBernard
12302KevinMalone
12305PamBeesley

Exemple avec LEFT JOIN

Tout d'abord, nous voulons voir toutes les personnes qui ont acheté Harry Potter et l'école des sorciers chez nous et vérifier si elles ont également acheté Harry Potter et la chambre des secrets.

Pour obtenir ce résultat, nous utilisons LEFT JOIN avec une liste de ceux qui ont acheté le premier livre inclus dans la clause FROM de la requête (table de gauche).

SELECT 
  ps.product_id, 
  ps.first_name, 
  ps.last_name, 
  cs.product_id, 
  cs.first_name, 
  cs.last_name
FROM philosophers_stone ps
LEFT JOIN chamber_of_secrets cs
ON ps.customer_id = cs.customer_id;

Cela nous permet de conserver tous les acheteurs de Harry Potter et l'école des sorciers même s'il n'y a pas d'enregistrements correspondants dans la deuxième table :

product_idfirst_namelast_nameproduct_idfirst_namelast_name
11AndyBernard12AndyBernard
11RobertCaliforniaNULLNULLNULL
11PamBeesley12PamBeesley
11OscarMartinezNULLNULLNULL

Maintenant, nous constatons que deux clients ont acheté le premier livre de la série mais pas le second. Nous pourrions leur recommander le deuxième livre lors de notre prochaine campagne de marketing.

Exemple avec FULL JOIN

Mais qu'en est-il des clients qui n'ont acheté que le deuxième livre, mais pas le premier ? Il serait également intéressant de le savoir.

Au lieu d'écrire une requête séparée pour repérer ce groupe de clients, il est préférable d'utiliser FULL JOIN qui nous fournit l'image complète : ceux qui ont acheté seulement le premier livre, ceux qui ont acheté seulement le deuxième livre, et ceux qui ont acheté les deux livres :

SELECT 
  ps.product_id, 
  ps.first_name, 
  ps.last_name, 
  cs.product_id, 
  cs.first_name, 
  cs.last_name
FROM philosophers_stone ps
FULL JOIN chamber_of_secrets cs
ON ps.customer_id = cs.customer_id;
product_idfirst_namelast_nameproduct_idfirst_namelast_name
11AndyBernard12AndyBernard
11RobertCaliforniaNULLNULLNULL
11PamBeesley12PamBeesley
11OscarMartinezNULLNULLNULL
NULLNULLNULL12KevinMalone

Ça a l'air bien ! Maintenant, nous pouvons facilement comparer deux groupes de clients et trouver des opportunités pour de bonnes recommandations de livres. Les JOINs externes peuvent être très pratiques !

Il est temps de pratiquer Les jointures en SQL!

La jonction de tables est l'une des compétences fondamentales requises pour l'utilisation efficace de SQL dans l'analyse des données et la création de rapports. Ce n'est pas si difficile, mais il faut beaucoup de pratique avec Les jointures en SQL pour éviter les pièges comme les enregistrements manquants et les doublons inattendus.

Je vous recommande de commencer par le Les jointures en SQL cours interactif. Il couvre tous les principaux types de jointures, la jointure d'une table avec elle-même, la jointure de plusieurs tables dans une même requête et la jointure de tables sur des colonnes non clés. Vous trouverez plus de détails sur ce cours dans cet article de présentation.

Bonus. Voici les 10 meilleures questions d'entretien sur les JOIN SQL, avec les réponses.

Merci de votre lecture et bon apprentissage !