Jointures SQL
Les jointures combinent des données provenant de plusieurs tables : nom du client, catégorie du produit, détails de la région, etc.
Rappel : INNER JOIN
INNER JOIN retourne uniquement les lignes qui ont une correspondance dans les deux tables :
SELECT
v.id,
v.montant,
v.date_vente,
c.nom AS client_nom,
c.segment
FROM ventes v
INNER JOIN clients c ON v.client_id = c.id
Aliases de table
Les alias v et c simplifient l'écriture quand on travaille avec plusieurs tables. Utilisez des alias courts et cohérents : v pour ventes, c pour clients, p pour produits.
Si une vente référence un client_id qui n'existe pas dans la table clients, cette ligne de vente disparaît du résultat. C'est le comportement par défaut d'INNER JOIN.
Que se passe-t-il avec INNER JOIN si une vente a un client_id sans correspondance dans la table clients ?
LEFT JOIN
LEFT JOIN conserve toutes les lignes de la table de gauche, même si elles n'ont pas de correspondance dans la table de droite. Les colonnes manquantes sont remplies avec NULL.
SELECT
v.id,
v.montant,
c.nom AS client_nom,
c.segment
FROM ventes v
LEFT JOIN clients c ON v.client_id = c.id
Ici, toutes les ventes apparaissent dans le résultat. Si une vente n'a pas de client correspondant, client_nom et segment valent NULL.
| Type | Lignes retournées | Cas d'usage |
|---|---|---|
| INNER JOIN | Seulement les correspondances | Enrichir les données quand la correspondance est garantie |
| LEFT JOIN | Toutes les lignes de la table de gauche | Conserver toutes les données même sans correspondance |
En pratique
En BI, on utilise souvent LEFT JOIN pour ne pas perdre de données. Une vente sans client identifié reste pertinente pour le CA global — on ne veut pas la supprimer du résultat.
Jointures multiples
On peut joindre plusieurs tables dans la même requête :
SELECT
v.id,
v.montant,
v.date_vente,
c.nom AS client_nom,
c.segment,
p.nom AS produit_nom,
p.categorie
FROM ventes v
INNER JOIN clients c ON v.client_id = c.id
INNER JOIN produits p ON v.produit_id = p.id
Chaque JOIN ajoute des colonnes au résultat. L'ordre des jointures n'a pas d'impact sur le résultat (le moteur SQL optimise automatiquement), mais lisez la requête de gauche à droite : on part des ventes, on enrichit avec les clients, puis avec les produits.
Quelle est la différence entre INNER JOIN et LEFT JOIN ?
Combiner JOIN, CTEs et window functions
Exemple : « Classement des segments clients par CA, avec le détail produit. »
WITH ventes_enrichies AS (
SELECT
v.montant,
v.date_vente,
c.segment,
p.categorie
FROM ventes v
INNER JOIN clients c ON v.client_id = c.id
INNER JOIN produits p ON v.produit_id = p.id
),
ca_par_segment AS (
SELECT
segment,
SUM(montant) AS chiffre_affaires
FROM ventes_enrichies
GROUP BY segment
),
avec_rang AS (
SELECT
segment,
chiffre_affaires,
RANK() OVER (ORDER BY chiffre_affaires DESC) AS rang
FROM ca_par_segment
)
SELECT segment, chiffre_affaires, rang
FROM avec_rang
ORDER BY rang
Le flux logique :
- CTE 1 —
ventes_enrichies: jointures pour assembler les données de trois tables - CTE 2 —
ca_par_segment: agrégation par segment client - CTE 3 —
avec_rang: classement avec RANK() - SELECT final : résultat ordonné
Les CTEs comme pipeline
Les CTEs transforment une requête complexe en pipeline lisible. Chaque CTE est une étape nommée : enrichissement (JOIN), agrégation (GROUP BY), calcul analytique (window function).
Exemple combiné avec LAG
On peut aussi combiner jointures et LAG pour une analyse temporelle enrichie :
WITH ventes_enrichies AS (
SELECT
strftime('%Y-%m', v.date_vente) AS mois,
c.segment,
v.montant
FROM ventes v
INNER JOIN clients c ON v.client_id = c.id
),
ca_mensuel_segment AS (
SELECT
mois,
segment,
SUM(montant) AS chiffre_affaires
FROM ventes_enrichies
GROUP BY mois, segment
),
avec_evolution AS (
SELECT
mois,
segment,
chiffre_affaires,
LAG(chiffre_affaires, 1, 0) OVER (
PARTITION BY segment
ORDER BY mois
) AS ca_precedent
FROM ca_mensuel_segment
)
SELECT
mois,
segment,
chiffre_affaires,
chiffre_affaires - ca_precedent AS evolution
FROM avec_evolution
ORDER BY mois, segment
Cette requête combine JOIN (enrichissement), GROUP BY (agrégation) et LAG avec PARTITION BY (évolution par segment), structurés en CTEs.
À retenir
Points clés
- INNER JOIN : seulement les correspondances — utiliser quand la relation est garantie
- LEFT JOIN : conserve la table de gauche — utiliser en BI pour ne pas perdre de données
- Les aliases de table (
v,c,p) sont indispensables avec les jointures multiples - La combinaison JOIN + CTE + window function couvre la plupart des besoins analytiques
- Organisez la requête en pipeline de CTEs : enrichissement → agrégation → calcul analytique