🔗 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;