🗂️ 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)