Une jointure recolle deux tables
Les bases de données relationnelles éclatent les données dans plusieurs tables, et ce n'est pas un hasard : les clients dans une table, les commandes dans une autre, les produits dans une troisième. Comme ça, chaque information vit à un seul endroit. Sauf que dès qu'on veut répondre à une vraie question (« quels clients ont commandé quoi ? »), il faut bien recoller les morceaux. C'est précisément le rôle d'une jointure SQLite.
L'INNER JOIN est l'outil de base. Il associe les lignes de deux tables dès qu'une condition correspond, et met tout le reste à la poubelle.
Trois clients, trois commandes, mais Chen n'a aucune commande — donc Chen n'apparaît pas. C'est ça, la logique du inner : seules les lignes qui matchent survivent.
Le modèle mental : associer les lignes, puis filtrer
Voici comment lire une jointure INNER JOIN en SQLite : on prend chaque ligne de la première table, on la confronte à chaque ligne de la seconde, et on ne garde la paire que si la condition du ON est vraie. Conceptuellement, c'est un énorme produit cartésien suivi d'un filtre. En pratique, SQLite ne procède pas comme ça (il s'appuie sur les index dès qu'il peut), mais ce modèle reste juste pour anticiper le résultat.
Quelques bonnes habitudes à prendre :
- Donnez un alias aux tables (
customers AS c) dès que vous comptez les évoquer plusieurs fois. Ça allège la lecture. - Préfixez les colonnes (
c.name,o.total) quand les deux tables pourraient légitimement les contenir. - L'ordre dans
ON o.customer_id = c.idn'a aucune importance —c.id = o.customer_iddonne exactement le même résultat.
INNER JOIN ou JOIN : quelle différence ?
En SQLite (comme en SQL standard), un JOIN tout seul équivaut à un INNER JOIN. Le mot-clé INNER est facultatif.
Les deux écritures produisent le même plan d'exécution et renvoient les mêmes lignes. Écrire INNER JOIN en toutes lettres apporte un petit gain de lisibilité dans du code qui mélange plusieurs types de jointures : l'intention saute aux yeux quand un LEFT JOIN apparaît quelques lignes plus loin.
ON ou USING : que choisir ?
Lorsque les colonnes de jointure portent le même nom dans les deux tables, USING (colonne) est plus concis que ON a.col = b.col :
USING (customer_id) fait deux choses d'un coup : il fait correspondre les lignes ayant le même customer_id et fusionne la colonne pour qu'elle n'apparaisse qu'une seule fois dans le résultat. À sortir du placard quand les deux côtés portent vraiment le même nom de colonne. En revanche, gardez la clause ON dès que les noms diffèrent (orders.customer_id = customers.id) ou que la condition va au-delà d'une simple égalité.
Joindre plusieurs tables avec INNER JOIN
Pour faire un inner join sur 3 tables en SQLite, il suffit d'enchaîner les clauses JOIN ... ON .... Chacune relie le résultat intermédiaire à une nouvelle table.
Lisez-le de haut en bas : les clients sont reliés aux commandes, et les commandes sont reliées aux articles. Chaque ligne du résultat correspond à une combinaison client–commande–article. Tout ce qui n'a pas de correspondance à un moment de la chaîne est écarté — c'est la règle de l'inner join appliquée à chaque étape.
Filtrer avec WHERE
La clause ON indique comment apparier les lignes. WHERE, lui, filtre le résultat déjà apparié. Dans le cas précis d'une jointure SQLite de type inner join, glisser une condition supplémentaire dans ON ou dans WHERE donne exactement les mêmes lignes — mais la convention reste claire : les conditions de jointure vont dans ON, et les filtres de lignes dans WHERE.
On peut lire ça comme : « on joint customers et orders, puis on ne garde que les clients du Royaume-Uni avec une commande de plus de 20 ». Deux rôles, deux clauses — votre vous du futur vous remerciera. (Dès que vous commencerez à écrire des LEFT JOIN, la distinction entre ON et WHERE cessera d'être purement cosmétique, mais ce sera pour la page suivante.)
Plusieurs conditions dans le ON
La clause ON accepte n'importe quelle expression booléenne, pas seulement une simple égalité. Pratique quand la relation porte sur plusieurs colonnes, ou quand vous voulez filtrer la table de droite directement au moment de la jointure.
La commande annulée disparaît parce que la seconde condition n'est pas remplie. Pour une jointure interne, vous pourriez tout aussi bien écrire WHERE o.status = 'paid' et obtenir le même résultat. La version avec ON a l'avantage de garder la logique « qu'est-ce qui compte comme une correspondance » au plus près de la jointure elle-même.
Pièges classiques
Voici quelques points qui font souvent trébucher :
- Oublier la clause
ON.FROM a INNER JOIN bsansONest une erreur de syntaxe en SQLite. (En revanche, une simple virgule —FROM a, b— compile sans broncher, mais produit un produit cartésien, ce qui n'est presque jamais ce que vous vouliez.) - Des doublons inattendus. Si un client a passé trois commandes, son nom apparaîtra trois fois dans le résultat. Ce n'est pas un bug, c'est le comportement normal d'une jointure. Utilisez
GROUP BYpour agréger si vous voulez une seule ligne par client. - Des lignes manquantes. Si un client aurait dû figurer dans le résultat mais n'y est pas, c'est que la condition de jointure n'a pas matché — vérifiez la présence de
NULLsur les colonnes de jointure, ou passez à unLEFT JOIN. - Noms de colonnes ambigus.
SELECT id FROM customers JOIN orders ON ...échoue parce que les deux tables ont une colonneid. Il faut qualifier :c.idouo.id.
La suite : LEFT JOIN
INNER JOIN est parfait quand l'absence de correspondance signifie « on ignore cette ligne ». Mais parfois, on veut lister tous les clients, y compris ceux qui n'ont jamais passé commande, avec des NULL à la place des données manquantes. C'est précisément le rôle de LEFT JOIN, qu'on aborde juste après.
Questions fréquentes
À quoi sert INNER JOIN en SQLite ?
INNER JOIN ne renvoie que les lignes qui ont une correspondance dans les deux tables, selon la condition définie dans ON. Toutes les lignes sans correspondance, d'un côté comme de l'autre, sont écartées. C'est d'ailleurs le comportement par défaut : en SQLite, JOIN et INNER JOIN sont strictement équivalents.
Quelle est la différence entre INNER JOIN et LEFT JOIN en SQLite ?
INNER JOIN ne garde que les lignes appariées. LEFT JOIN, lui, conserve toutes les lignes de la table de gauche et remplit avec des NULL côté droit quand il n'y a pas de correspondance. En pratique : utilisez INNER JOIN quand une absence de correspondance signifie « on ignore cette ligne », et LEFT JOIN quand on veut quand même la voir apparaître.
Peut-on faire un INNER JOIN sur trois tables en SQLite ?
Oui, il suffit d'enchaîner une nouvelle clause JOIN ... ON .... Chaque jointure relie le résultat courant à une nouvelle table. Il n'y a pas de limite stricte, mais au-delà de quatre ou cinq tables la requête devient vite illisible — c'est souvent là qu'une CTE rend bien service.
Quand utiliser USING plutôt que ON ?
USING (colonne) est un raccourci pratique quand la colonne de jointure porte le même nom dans les deux tables. C'est plus concis et la colonne dupliquée est fusionnée en une seule dans le résultat. Dès que les noms diffèrent ou que la condition se complique, on revient à ON.