🗂️ Fiche mémo rapide#
| Type de JOIN | Fonction | Inclut les lignes de… | Syntaxe |
|---|---|---|---|
INNER JOIN | Intersections | correspondance dans les deux tables | ... FROM A JOIN B ON A.id = B.id |
LEFT JOIN | Priorité à la gauche | toutes lignes de A + celles de B qui matchent | ... FROM A LEFT JOIN B ON A.id = B.id |
RIGHT JOIN | Priorité à la droite | toutes lignes de B + celles de A qui matchent | ... FROM A RIGHT JOIN B ON A.id = B.id |
FULL OUTER JOIN | Union + nulls | toutes les lignes de A et B | ... FROM A FULL JOIN B ON A.id = B.id |
CROSS JOIN | Produit cartésien | toutes combinaisons possibles | ... FROM A CROSS JOIN B |
SELF JOIN | Joindre une table avec elle-même | utile pour hiérarchie / comparaison | FROM A a1 JOIN A a2 ON a1.manager_id = a2.id |
📘 Exemples commentés#
Création d’une base#
-- Clients
CREATE TABLE clients (
client_id INTEGER,
nom TEXT
);
INSERT INTO clients VALUES
(1, 'Alice'),
(2, 'Bob'),
(3, 'Charlie');
-- Commandes
CREATE TABLE commandes (
commande_id INTEGER,
client_id INTEGER,
produit TEXT
);
INSERT INTO commandes VALUES
(101, 1, 'Chaise'),
(102, 1, 'Table'),
(103, 2, 'Canapé');
✅ INNER JOIN (seulement ceux qui ont commandé)#
SELECT c.nom, cmd.produit
FROM clients c
INNER JOIN commandes cmd ON c.client_id = cmd.client_id;
✅ LEFT JOIN (tous les clients, même sans commandes)#
SELECT c.nom, cmd.produit
FROM clients c
LEFT JOIN commandes cmd ON c.client_id = cmd.client_id;
✅ RIGHT JOIN (toutes les commandes, même sans client connu)#
(non supporté par SQLite, supporté par PostgreSQL et DuckDB)
SELECT c.nom, cmd.produit
FROM clients c
RIGHT JOIN commandes cmd ON c.client_id = cmd.client_id;
✅ FULL OUTER JOIN (tous les clients et commandes, même sans correspondance)#
SELECT c.nom, cmd.produit
FROM clients c
FULL OUTER JOIN commandes cmd ON c.client_id = cmd.client_id;
✅ CROSS JOIN (tous les couples clients-produits)#
SELECT c.nom, cmd.produit
FROM clients c
CROSS JOIN commandes cmd;
✅ SELF JOIN (cas d’un organigramme)#
CREATE TABLE employes (
emp_id INT,
nom TEXT,
manager_id INT
);
INSERT INTO employes VALUES
(1, 'Alice', NULL),
(2, 'Bob', 1),
(3, 'Charlie', 1),
(4, 'Dave', 2);
-- Lister chaque employé avec son manager
SELECT e1.nom AS employe, e2.nom AS manager
FROM employes e1
LEFT JOIN employes e2 ON e1.manager_id = e2.emp_id;
⚠️ Pièges classiques#
- Cardinalité mal maîtrisée : un JOIN 1→N ou N→N crée des doublons ou multiplie les montants (ex : ventes × produits × promotions).
- Oublier la condition
ONavecINNER JOIN→ produit cartésien non désiré. NULL: unJOINsurNULL = NULLne renvoie rien → utiliserIS NULL.LEFT JOIN: attention à ne pas appliquer des conditionsWHEREsur la table de droite, sinon tu “annules” le LEFT JOIN.
-- Mauvais (filtre casse le LEFT JOIN)
SELECT * FROM clients c
LEFT JOIN commandes cmd ON c.client_id = cmd.client_id
WHERE cmd.produit = 'Chaise'; -- ← attention ici
-- Correct
SELECT * FROM clients c
LEFT JOIN commandes cmd ON c.client_id = cmd.client_id
WHERE cmd.produit = 'Chaise' OR cmd.produit IS NULL;
🏋️♂️ Entraînement#
- Liste les clients qui ont commandé au moins un produit.
- Liste tous les clients, même ceux sans commande, avec le nom du produit (ou NULL).
- Combien de produits a commandé chaque client (y compris ceux avec 0) ?
- Liste tous les couples d’employés/manager.
- Effectue un
CROSS JOINet affiche les 5 premières lignes.
import duckdb
import pandas as pd
duckdb.sql("""
CREATE TABLE clients AS SELECT * FROM (
VALUES (1, 'Alice'), (2, 'Bob'), (3, 'Charlie')
) AS t(client_id, nom);
CREATE TABLE commandes AS SELECT * FROM (
VALUES (101, 1, 'Chaise'), (102, 1, 'Table'), (103, 2, 'Canapé')
) AS t(commande_id, client_id, produit);
""")
# Exemple de JOIN
df = duckdb.sql("""
SELECT c.nom, cmd.produit
FROM clients c
LEFT JOIN commandes cmd ON c.client_id = cmd.client_id
""").df()
print(df)