🔗 Concept des jointures
Les jointures permettent de combiner des données de plusieurs tables en une seule requête. La condition ON définit la relation entre les tables.
Table clients : id | nom | ville
1 | Alice | Paris
2 | Bob | Lyon
Table commandes : id | client_id | total
1 | 1 | 150€
2 | 1 | 50€
3 | 2 | 200€
JOIN sur clients.id = commandes.client_id :
nom | commande.id | total
Alice | 1 | 150€
Alice | 2 | 50€
Bob | 3 | 200€
⚓ INNER JOIN
Retourne uniquement les lignes qui ont une correspondance dans les deux tables.
-- Syntaxe de base
SELECT p.nom, p.prix, c.nom AS categorie
FROM produits p
INNER JOIN categories c ON p.categorie_id = c.id;
-- INNER est optionnel (JOIN seul = INNER JOIN)
SELECT p.nom, c.nom AS categorie
FROM produits p
JOIN categories c ON p.categorie_id = c.id;
-- Avec WHERE en plus
SELECT p.nom, p.prix, c.nom AS categorie
FROM produits p
JOIN categories c ON p.categorie_id = c.id
WHERE p.prix > 100
ORDER BY p.prix DESC;
Les produits sans catégorie (
categorie_id IS NULL) sont exclus du résultat avec INNER JOIN.⬅️ LEFT JOIN (et RIGHT JOIN)
LEFT JOIN retourne toutes les lignes de la table gauche, avec les colonnes de droite à NULL quand il n'y a pas de correspondance.
-- Tous les produits, avec ou sans catégorie
SELECT p.nom, p.prix, c.nom AS categorie
FROM produits p
LEFT JOIN categories c ON p.categorie_id = c.id;
-- Anti-join : produits SANS catégorie
SELECT p.id, p.nom
FROM produits p
LEFT JOIN categories c ON p.categorie_id = c.id
WHERE c.id IS NULL;
-- Clients avec le nombre de commandes (0 si aucune)
SELECT cl.nom, COUNT(co.id) AS nb_commandes
FROM clients cl
LEFT JOIN commandes co ON cl.id = co.client_id
GROUP BY cl.id, cl.nom;
-- Clients sans aucune commande (anti-join)
SELECT cl.nom
FROM clients cl
LEFT JOIN commandes co ON cl.id = co.client_id
WHERE co.id IS NULL;
Préférez
LEFT JOIN à RIGHT JOIN pour la lisibilité : mettez toujours la table "principale" à gauche et la table "optionnelle" à droite.🔀 Jointures multiples
On peut chaîner autant de jointures que nécessaire. MySQL supporte jusqu'à 61 tables par requête.
-- 4 tables : commandes ← clients, commande_produits → produits → categories
SELECT
cl.nom AS client,
co.date_commande,
co.statut,
p.nom AS produit,
cat.nom AS categorie,
cp.quantite,
cp.prix_unitaire
FROM commandes co
JOIN clients cl ON co.client_id = cl.id
JOIN commande_produits cp ON co.id = cp.commande_id
JOIN produits p ON cp.produit_id = p.id
LEFT JOIN categories cat ON p.categorie_id = cat.id
ORDER BY co.date_commande DESC, cl.nom;
🪞 Self JOIN (auto-jointure)
Une table se joint avec elle-même. Nécessite impérativement des alias.
-- Exemple : table employes avec manager_id auto-référencé
-- employes : id, nom, poste, manager_id (FK vers employes.id)
SELECT
e.nom AS employe,
e.poste,
m.nom AS manager
FROM employes e
LEFT JOIN employes m ON e.manager_id = m.id
ORDER BY m.nom, e.nom;
🔄 UNION
UNION combine les résultats de deux SELECT en une seule liste. Les colonnes doivent correspondre en nombre et en type.
-- UNION : élimine les doublons
SELECT nom, 'client' AS type FROM clients
UNION
SELECT nom, 'categorie' AS type FROM categories
ORDER BY nom;
-- UNION ALL : conserve les doublons (plus rapide car pas de déduplication)
SELECT ville FROM clients WHERE ville IS NOT NULL
UNION ALL
SELECT 'Inconnue' AS ville
LIMIT 10;
💡 Patterns avancés
Compter avec jointure
-- COUNT(co.id) et non COUNT(*) : évite de compter les NULL du LEFT JOIN
SELECT cl.nom, COUNT(co.id) AS nb, COALESCE(SUM(co.total), 0) AS ca
FROM clients cl
LEFT JOIN commandes co ON cl.id = co.client_id
GROUP BY cl.id, cl.nom
HAVING nb > 0
ORDER BY ca DESC;
CROSS JOIN
-- Toutes les combinaisons clients × statuts possible
SELECT cl.nom, s.statut
FROM clients cl
CROSS JOIN (
SELECT 'attente' AS statut UNION ALL SELECT 'livree'
) s;