Le CROSS JOIN est une instruction SQL qui associe systématiquement chaque ligne d’une table à toutes les lignes d’une seconde table. Le résultat produit s’appelle un produit cartésien, et sa taille est égale au nombre de lignes de la première table multiplié par celui de la seconde. Si la table A contient 10 enregistrements et la table B en contient 20, le moteur SQL retourne exactement 200 combinaisons générées sans aucun critère de sélection. Aucune correspondance entre les colonnes n’est requise pour que l’opération s’exécute, ce qui rend ce type de combinaison fondamentalement différent des autres opérations de liaison. C’est précisément cette absence de condition qui donne au CROSS JOIN un comportement unique parmi les opérations multi-tables du langage SQL.
Table des matières
Syntaxe générique pour CROSS JOIN
La syntaxe du CROSS JOIN est la plus concise parmi les opérations de liaison SQL, car elle ne contient ni clause ON ni clause USING. En SQL standard ISO/IEC, la jointure croisée s’écrit explicitement sans aucune condition de liaison rattachée à la déclaration. Dans MySQL, CROSS JOIN, JOIN et INNER JOIN sont des synonymes syntaxiques, mais leur comportement diverge dès qu’une clause ON est absente. Pour garantir la lisibilité du code et exprimer une intention claire, la forme explicite CROSS JOIN est toujours préférable à la notation implicite avec une virgule. Une écriture explicite facilite aussi la détection d’un produit cartésien accidentel lors d’une revue de code.
La syntaxe standard pour effectuer ce type de combinaison exhaustive s’écrit de la manière suivante :
SELECT colonne1, colonne2
FROM table1
CROSS JOIN table2;
Cette instruction retourne l’intégralité des associations possibles entre les enregistrements des deux tables impliquées. Sans clause WHERE, aucun filtre n’est appliqué et toutes les paires sont incluses dans le résultat final.
La notation implicite avec une virgule produit un résultat identique dans MySQL, bien qu’elle soit fortement déconseillée :
SELECT colonne1, colonne2
FROM table1, table2;
Cette écriture masque l’intention du développeur et complique la détection d’une combinaison non intentionnelle dans une base de données. Optez systématiquement pour la forme explicite afin de rendre chaque opération multi-table immédiatement identifiable à la lecture.
Pourquoi utiliser une jointure croisée ?
Le CROSS JOIN répond à des besoins métier précis qui nécessitent de générer un ensemble exhaustif de paires à partir de deux listes distinctes. Ce type de combinaison totale est utile pour associer chaque produit à chaque variante disponible, comme une couleur ou une taille, dans un catalogue e-commerce. Il s’applique aussi à la génération de grilles de planification, de calendriers de matchs sportifs ou de matrices de tests automatisés. Un autre usage documenté consiste à croiser une table de dates avec une table d’entités pour détecter les périodes sans activité enregistrée. Dans ce contexte, la jointure croisée agit comme un générateur de référentiel complet, que l’on confronte ensuite aux données existantes.
L’exemple suivant illustre la génération de toutes les variantes possibles d’un article à partir de deux tables de référence :
SELECT couleurs.nom_couleur, tailles.nom_taille
FROM couleurs
CROSS JOIN tailles;
Si la table couleurs contient 3 entrées et la table tailles en contient 3, le résultat retourne exactement 9 paires distinctes. Vérifiez que ce chiffre correspond bien au produit entre le nombre de lignes de chaque table avant d’exploiter le résultat.
Comment effectuer une jointure croisée ?
Réaliser un CROSS JOIN consiste à nommer deux tables dans la requête sans spécifier de condition de correspondance entre leurs colonnes. Il est courant de combiner cette opération avec une clause WHERE afin de restreindre le jeu de paires au périmètre métier pertinent. Avant d’exécuter cette opération, estimer la taille du résultat attendu permet d’éviter de saturer la mémoire du serveur avec un volume de données non maîtrisé. Le calcul est simple : multiplier le nombre de lignes de chaque table donne la taille exacte du produit cartésien brut obtenu. Pour les tables volumineuses, il est conseillé de tester d’abord la requête avec une clause LIMIT afin de valider la structure du résultat avant de traiter l’intégralité des données.
L’exemple suivant associe chaque employé à chaque projet ouvert pour établir une liste de missions potentielles :
SELECT employes.nom, projets.titre
FROM employes
CROSS JOIN projets
WHERE projets.statut = 'ouvert';
La clause WHERE réduit le périmètre en excluant les projets dont le statut diffère de « ouvert » parmi toutes les associations générées. Contrôlez que chaque employé apparaît bien autant de fois qu’il y a de projets ouverts dans la table projets.
Le cas pratique suivant détecte les produits sans vente sur une période donnée, en confrontant un référentiel complet de dates et de produits aux ventes enregistrées :
SELECT d.date_vente, p.nom_produit, v.montant
FROM dates d
CROSS JOIN produits p
LEFT JOIN ventes v
ON d.date_vente = v.date_vente
AND p.id_produit = v.id_produit
WHERE v.montant IS NULL;
Ce résultat liste chaque combinaison date-produit pour laquelle aucun enregistrement de vente n’existe dans la table ventes. Vérifiez que la colonne montant affiche bien NULL pour toutes les lignes retournées, signe que l’absence de vente est correctement identifiée.
Quelle opération est la plus rapide : la jointure croisée ou la jointure interne ?
La rapidité d’exécution dépend directement du volume de données impliqué et de la présence ou non d’une condition de filtrage dans la requête. Sans clause WHERE, la combinaison exhaustive génère systématiquement un résultat plus volumineux qu’une opération de liaison conditionnelle, ce qui implique un coût CPU et mémoire plus élevé. La documentation MySQL confirme que ces deux instructions sont syntaxiquement équivalentes en l’absence de clause ON, mais leurs plans d’exécution divergent dès qu’une condition est introduite. Une liaison conditionnelle avec un index bien défini sur la colonne de correspondance s’exécutera presque toujours plus rapidement que la même logique exprimée via un produit cartésien filtré avec WHERE. Sur des volumes de plusieurs centaines de milliers de lignes, cet écart de performance devient significatif et peut transformer une requête rapide en opération bloquante.
Quel est l’impact des jointures croisées sur les performances ?
Le CROSS JOIN est l’opération multi-table qui sollicite le plus les ressources du serveur, en raison de la croissance exponentielle du nombre de combinaisons produites. Pour deux tables contenant chacune 1 000 enregistrements, le moteur SQL doit traiter un million de paires avant d’appliquer tout critère de réduction. Cette explosion combinatoire mobilise une quantité importante de mémoire RAM et ralentit les autres requêtes qui s’exécutent simultanément sur la même instance. L’indexation des colonnes de liaison ne bénéficie pas directement à l’opération de croisement elle-même, puisqu’aucune condition de correspondance n’est évaluée durant la phase de génération des paires. En revanche, les index définis sur les colonnes utilisées dans les clauses WHERE ou dans les liaisons conditionnelles qui suivent le croisement contribuent à réduire le coût du filtrage ultérieur.
La jointure croisée est-elle une mauvaise pratique ?
Un CROSS JOIN explicitement déclaré, avec une justification métier claire, n’est pas une mauvaise pratique en soi. Le problème survient lorsque cette opération apparaît de manière accidentelle, souvent à cause d’une clause ON omise dans une requête de liaison classique. Ce type d’erreur de conception est l’une des causes les plus fréquentes de lenteurs inexpliquées et de volumes de résultats anormalement élevés en production. Un produit cartésien non intentionnel produit par une notation implicite est difficile à détecter sans analyser le plan d’exécution de la requête. À l’inverse, un CROSS JOIN explicitement écrit avec ce mot-clé traduit une intention documentée, ce qui le rend acceptable et maintenable dans le code.
Comment éviter les jointures croisées ?
Pour prévenir les combinaisons accidentelles, la règle fondamentale consiste à toujours associer une clause ON ou USING à chaque opération de liaison écrite dans une requête SQL. Remplacer la notation implicite avec une virgule par la syntaxe explicite INNER JOIN ... ON élimine la grande majorité des produits cartésiens non intentionnels dans une base de code existante. L’instruction EXPLAIN permet d’analyser le plan d’exécution d’une requête et de détecter la présence d’une opération de type ALL sur deux tables sans condition de liaison. Certains environnements de développement SQL signalent automatiquement une liaison sans condition comme un avertissement lors de l’analyse statique du code. Vérifier systématiquement le nombre de lignes retourné après chaque requête multi-tables permet également de repérer rapidement un volume anormal dû à un croisement non maîtrisé.
L’exemple suivant montre comment corriger une combinaison accidentelle entre deux tables liées par un identifiant commun :
-- Écriture incorrecte : produit cartésien non intentionnel
SELECT * FROM commandes, clients;
-- Écriture corrigée : liaison conditionnelle explicite
SELECT *
FROM commandes
INNER JOIN clients ON commandes.id_client = clients.id_client;
La première instruction retourne toutes les paires possibles entre commandes et clients, indépendamment de toute relation entre les données. La seconde ne conserve que les enregistrements où id_client est identique dans les deux tables, ce qui correspond au comportement attendu.
Sources: MySql, Postgres