Je vérifie la clé de jointure, le type de jointure et le nombre de lignes obtenu. Une jointure peut exclure des enregistrements ou en dupliquer. Voici comment choisir entre INNER JOIN et LEFT JOIN, puis repérer le fan-out.
Pourquoi relier des tables ?
On relie des tables pour retrouver une information répartie sans la recopier partout. Dans une boutique en ligne, les coordonnées d’un client appartiennent à la table clients, tandis que ses achats sont stockés dans la table commandes.

Si chaque commande répétait le nom, l’adresse et l’e-mail du client, ces données seraient dupliquées. Une modification d’adresse obligerait à mettre à jour plusieurs lignes. Une seule ligne oubliée suffirait à créer des informations contradictoires. Séparer les clients et les commandes limite ces incohérences et évite les répétitions inutiles.
La colonne customer_id relie les deux tables. Elle identifie un client dans clients et figure dans commandes pour indiquer à qui appartient chaque commande. Dans la table commandes, c’est une clé étrangère : elle référence la clé du client dans clients.
Voici une structure minimale, suivie d’une requête qui utilise des alias explicites pour distinguer les deux tables :
CREATE TABLE clients (
customer_id INT PRIMARY KEY,
email VARCHAR(255)
);
CREATE TABLE commandes (
order_id INT PRIMARY KEY,
customer_id INT,
-- La clé étrangère référence un client existant.
FOREIGN KEY (customer_id) REFERENCES clients(customer_id)
);
-- c désigne la table clients, cmd désigne la table commandes.
SELECT c.customer_id, c.email, cmd.order_id
FROM clients AS c
JOIN commandes AS cmd
ON cmd.customer_id = c.customer_id;La condition ON précise comment les lignes se correspondent : ici, les valeurs de customer_id doivent être identiques. Cette liaison ne détermine pas encore quelles lignes seront conservées si une correspondance manque. C’est le type de jointure choisi — INNER JOIN ou LEFT JOIN, par exemple — qui fixe ce comportement. C’est souvent là que commencent les pièges.
Que retourne un INNER JOIN ?
Un INNER JOIN ne conserve que les lignes pour lesquelles la condition ON trouve une correspondance dans les deux tables. Une ligne sans partenaire correspondant est exclue du résultat.

Dans l’exemple clients-commandes, une commande dont le customer_id ne correspond à aucun client n’apparaît pas. Un client qui n’a passé aucune commande n’apparaît pas non plus. Le résultat contient uniquement les associations valides entre les deux tables.
Voici une requête complète qui relie les commandes aux clients sur customer_id :
SELECT
o.order_id,
o.customer_id,
o.order_date,
c.customer_name
FROM orders AS o
INNER JOIN customers AS c
-- La jointure conserve uniquement les customer_id présents dans les deux tables.
ON o.customer_id = c.customer_id;Les alias o et c raccourcissent la requête et indiquent clairement de quelle table vient chaque colonne. Ils évitent aussi les ambiguïtés quand les tables contiennent des colonnes homonymes, comme customer_id. Écrire o.customer_id ou c.customer_id précise la source ; écrire seulement customer_id peut rendre la requête ambiguë.
Avant de valider le résultat, vérifiez deux points :
- La condition
ONcompare bien les clés qui définissent une correspondance métier. Une mauvaise condition peut exclure des lignes attendues ou créer des associations incorrectes. - Le périmètre attendu est bien celui des lignes appariées. Si vous devez aussi conserver les clients sans commande, ou les commandes sans client correspondant, un
INNER JOINne convient pas.
Un détail compte aussi : si une clé apparaît plusieurs fois dans une table, une ligne peut correspondre à plusieurs lignes de l’autre table. Le résultat contient alors plusieurs associations, pas nécessairement une ligne par client ou par commande. Quand les lignes sans correspondance doivent rester visibles, il faut choisir une autre forme de jointure.
Quand choisir un LEFT JOIN ?
Choisissez un LEFT JOIN lorsque toutes les lignes de la table placée à gauche doivent être conservées, même si la table de droite ne contient aucune correspondance. Avec les commandes à gauche et les clients à droite, chaque commande reste donc dans le résultat.

La jointure s’effectue ici sur customer_id. Les noms de tables sont précédés d’alias pour rendre la requête plus lisible.
SELECT
co.order_id,
co.customer_id,
cl.customer_name
FROM commandes AS co
LEFT JOIN clients AS cl
ON co.customer_id = cl.customer_id;Si une commande n’a pas de client correspondant, elle apparaît tout de même dans le résultat. Les colonnes provenant de clients, comme customer_name, valent alors NULL. Une commande dont customer_id ne trouve aucune valeur identique dans la table clients n’est donc pas supprimée.
La différence avec un INNER JOIN tient aux lignes conservées. Avec la même condition de jointure, un INNER JOIN ne retourne que les commandes pour lesquelles un client correspondant existe. Les commandes sans correspondance sont absentes du résultat. Le LEFT JOIN garde toutes les commandes et complète les colonnes du client quand une correspondance existe ; l’INNER JOIN limite le résultat aux correspondances entre les deux tables.
Le choix dépend donc de votre question métier. Vous cherchez toutes les commandes, y compris celles sans client associé ? LEFT JOIN. Vous ne voulez que les commandes reliées à un client ? INNER JOIN. Vérifiez aussi que la table de droite contient au plus une ligne par customer_id si vous attendez une ligne de résultat par commande. Sinon, plusieurs clients correspondant à une même commande peuvent produire plusieurs lignes. C’est le risque de duplication à surveiller dès qu’on ajoute d’autres tables à la requête.
Comment repérer le fan-out ?
Je repère le fan-out en comparant le nombre de lignes avant et après chaque jointure, puis en vérifiant la cardinalité réelle de la relation. Une hausse n’est pas forcément une anomalie : elle peut refléter une relation un-à-plusieurs. Elle devient un problème si elle gonfle des sommes ou des comptes dans la requête finale.

Par exemple, un client peut avoir plusieurs commandes, et une commande plusieurs articles. En joignant les commandes aux articles de commande, une commande apparaît donc sur plusieurs lignes. La jointure aux produits ajoute les informations produit à chaque ligne d’article ; elle ne garantit pas une ligne par commande.
Cette requête compare les volumes à chaque étape. Les jointures sont évaluées séparément pour isoler l’effet de chacune.
-- Compare le nombre de commandes et les lignes produites par chaque jointure.
SELECT 'commandes' AS etape, COUNT(*) AS nb_lignes
FROM commandes
UNION ALL
SELECT 'commandes + clients', COUNT(*)
FROM commandes c
JOIN clients cl ON cl.id_client = c.id_client
UNION ALL
SELECT 'commandes + articles', COUNT(*)
FROM commandes c
JOIN articles_commande ac ON ac.id_commande = c.id_commande
UNION ALL
SELECT 'commandes + articles + produits', COUNT(*)
FROM commandes c
JOIN articles_commande ac ON ac.id_commande = c.id_commande
JOIN produits p ON p.id_produit = ac.id_produit;Une jointure interne exclut les lignes sans correspondance. Pour mesurer le fan-out sur chaque commande, comptez ses lignes d’article. Le filtre HAVING ne garde ici que les commandes associées à plusieurs articles.
-- Repère les commandes qui produisent plusieurs lignes après la jointure.
SELECT
c.id_commande,
COUNT(ac.id_article_commande) AS nb_lignes_article
FROM commandes c
LEFT JOIN articles_commande ac
ON ac.id_commande = c.id_commande
GROUP BY c.id_commande
HAVING COUNT(ac.id_article_commande) > 1;Je vérifie aussi que les clés de jointure correspondent à la cardinalité attendue. Si vous additionnez le montant d’une commande après l’avoir jointe à ses articles, ce montant peut être répété sur chaque ligne et donc surcompté.
| Jointure | Lignes conservées | Absence de correspondance |
| INNER JOIN | Uniquement les lignes avec correspondance des deux côtés. | La ligne sans correspondance est exclue. |
| LEFT JOIN | Toutes les lignes de la table de gauche, avec les correspondances trouvées. | La ligne de gauche est conservée ; les colonnes de droite valent NULL. |
Vous savez quelle jointure choisir ?
Les jointures SQL réunissent des données réparties entre plusieurs tables sans répéter inutilement les mêmes informations. Le choix du type de jointure détermine les lignes conservées : INNER JOIN ne garde que les correspondances, tandis que LEFT JOIN préserve toutes les lignes de gauche et renvoie NULL lorsqu’il manque une correspondance à droite. Le fan-out rappelle qu’une jointure peut aussi multiplier les lignes, notamment quand une commande est associée à plusieurs articles. Je vérifie donc la clé, la condition ON et le volume obtenu après chaque jointure. Vous obtenez ainsi des résultats plus fiables et réduisez les erreurs d’interprétation dans vos analyses.
FAQ
- À quoi sert une jointure SQL ?
Une jointure SQL associe des lignes de plusieurs tables à partir d’une condition de correspondance, par exemple customer_id entre les clients et les commandes. - Quelle est la différence entre INNER JOIN et LEFT JOIN ?
INNER JOIN conserve uniquement les lignes qui correspondent dans les deux tables. LEFT JOIN conserve toutes les lignes de la table de gauche, même sans correspondance dans la table de droite. - Que contient une ligne sans correspondance après un LEFT JOIN ?
La ligne de gauche est conservée. Les colonnes provenant de la table de droite prennent la valeur NULL lorsqu’aucune correspondance n’est trouvée. - Pourquoi un INNER JOIN peut-il exclure des commandes ?
Parce qu’il ne conserve que les lignes qui satisfont la condition ON des deux côtés. Une commande sans client correspondant n’apparaît donc pas dans le résultat. - Qu’est-ce que le fan-out dans une jointure SQL ?
C’est un risque de multiplication des lignes lorsqu’une ligne est associée à plusieurs lignes dans une autre table, par exemple une commande liée à plusieurs articles. Comparez le nombre de lignes avant et après la jointure.
A propos de l’auteur
Je suis Franck Scandolera, expert en data engineering. J’aide les équipes à structurer et fiabiliser leurs données pour produire des analyses SQL exploitables et des applications métier intelligentes.
⭐ Analytics engineer, Data Analyst et Automatisation IA indépendant ⭐
Ref clients : Logis Hôtel, Yelloh Village, BazarChic, Fédération Football Français, Texdecor…
Mon terrain de jeu :
Data Analyst & Analytics engineering : tracking avancé (GA4, Matomo, Piano, GTM server, Tealium, Commander Act, e-commerce, CAPI, RGPD), entrepôt de données (BigQuery, Snowflake, PostgreSQL, ClickHouse), modèles (Airflow, dbt, Dataform), dashboards décisionnels (Looker, Power BI, Metabase, SQL, Python).
Automatisation IA des taches Data, Marketing, RH, compta etc : conception de workflows intelligents robustes (n8n, App Script, scraping) connectés aux API de vos outils et LLM (OpenAI, Mistral, Claude…).
Engineering IA pour créer des applications et agent IA sur mesure : intégration de LLM (OpenAI, Mistral…), RAG, assistants métier, génération de documents complexes, APIs, backends Node.js/Python.





