Visualisez comment les opérateurs ensemblistes combinent deux tables SQL
Table A — clients_france
| id | nom | ville |
|---|
Table B — clients_belgique
| id | nom | ville |
|---|
📊 Résultat
| id | nom | ville |
|---|
La confusion entre UNION, UNION ALL, INTERSECT et EXCEPT vient d’un problème de représentation : ces quatre opérateurs travaillent sur des ensembles de lignes, une notion abstraite difficile à saisir depuis une documentation textuelle seule. L’outil la rend immédiatement visible en colorant en vert les lignes conservées et en gris barré les lignes exclues dans chaque table source, tout en affichant simultanément le résultat final en bas. Le diagramme de Venn interactif change de forme à chaque clic pour montrer quelle zone de l’ensemble est retenue. En un coup d’œil, l’apprenant comprend pourquoi INTERSECT sur ces données retourne deux lignes, et pourquoi EXCEPT est asymétrique.
que sont les opérateurs ensemblistes en SQL
Les opérateurs ensemblistes (UNION, UNION ALL, INTERSECT, EXCEPT) combinent les résultats de deux requêtes SELECT distinctes en un seul résultat. Ils ne joignent pas les tables horizontalement comme JOIN : ils les empilent verticalement, ligne par ligne. Pour fonctionner, les deux requêtes doivent retourner le même nombre de colonnes, avec des types de données compatibles dans le même ordre.
L’outil utilise deux tables symétriques : clients_france (Alice, Bob, Claire, David) et clients_belgique (Claire, David, Emma, Frank). Claire et David apparaissent dans les deux tables avec les mêmes valeurs d’id, nom et ville, ce qui crée délibérément des doublons exploitables par chaque opérateur. Ce choix de données permet de voir concrètement comment chaque opérateur traite les lignes communes.
-- Table A : clients_france -- Table B : clients_belgique
-- id | nom | ville -- id | nom | ville
-- 1 | Alice | Paris -- 3 | Claire | Bordeaux
-- 2 | Bob | Lyon -- 4 | David | Paris
-- 3 | Claire | Bordeaux -- 5 | Emma | Bruxelles
-- 4 | David | Paris -- 6 | Frank | Liège
Les 4 opérateurs en détail
UNION — combinaison sans doublons
UNION fusionne toutes les lignes des deux tables en supprimant les doublons. Le moteur effectue une déduplication en comparant l’intégralité de chaque ligne : deux lignes sont considérées identiques si toutes leurs colonnes ont la même valeur. Dans l’outil, toutes les lignes des deux tables apparaissent en vert, mais Claire et David ne figurent qu’une seule fois dans le résultat final.
Le diagramme de Venn colorise les deux cercles entiers (zones A et B plus l’intersection), ce qui correspond à la totalité de l’union. Le résultat contient 6 lignes au lieu des 8 attendues si les doublons étaient conservés : les deux occurrences de Claire et David sont fusionnées en une seule.
SELECT id, nom, ville FROM clients_france
UNION
SELECT id, nom, ville FROM clients_belgique;
-- 6 lignes : Alice, Bob, Claire, David, Emma, Frank
-- Claire et David n'apparaissent qu'une seule fois
UNION ALL — combinaison avec doublons
UNION ALL empile toutes les lignes sans aucune déduplication. Il est plus rapide que UNION car le moteur n’a pas à trier ou comparer les lignes pour éliminer les doublons. Dans l’outil, toutes les lignes des deux tables sont en vert et le résultat contient 8 lignes : Claire et David apparaissent deux fois chacun.
UNION ALL est préférable à UNION quand les doublons sont impossibles structurellement (par exemple, deux tables partitionnées par période sans chevauchement), ou quand les doublons sont intentionnellement conservés pour un comptage ou une agrégation ultérieure.
SELECT id, nom, ville FROM clients_france
UNION ALL
SELECT id, nom, ville FROM clients_belgique;
-- 8 lignes : toutes les lignes des deux tables
-- Claire (id=3) et David (id=4) apparaissent deux fois
INTERSECT — lignes communes aux deux tables
INTERSECT ne retourne que les lignes présentes dans les deux tables simultanément. Dans l’outil, les lignes uniques à chaque table (Alice, Bob dans A ; Emma, Frank dans B) apparaissent grisées et barrées, tandis que Claire et David restent en vert. Le diagramme de Venn ne colore que l’intersection centrale.
La comparaison porte sur la totalité de la ligne, pas uniquement sur une clé. Si Claire avait id=3 dans clients_france mais id=33 dans clients_belgique, elle ne serait pas considérée comme commune malgré le même nom.
SELECT id, nom, ville FROM clients_france
INTERSECT
SELECT id, nom, ville FROM clients_belgique;
-- 2 lignes uniquement : Claire (id=3) et David (id=4)
-- Présentes avec les mêmes valeurs dans les deux tables
EXCEPT — lignes de A absentes de B
EXCEPT retourne les lignes de la première table qui ne figurent pas dans la seconde. C’est la différence ensembliste A − B. Dans l’outil, toutes les lignes de la table B sont grisées et barrées (elles ne contribuent pas au résultat), et seules Alice et Bob (absentes de clients_belgique) restent en vert dans la table A.
L’asymétrie de EXCEPT est son caractéristique la plus importante : A EXCEPT B et B EXCEPT A donnent des résultats entièrement différents. Inverser l’ordre des tables retournerait Emma et Frank (présentes dans B mais absentes de A), pas Alice et Bob.
SELECT id, nom, ville FROM clients_france
EXCEPT
SELECT id, nom, ville FROM clients_belgique;
-- 2 lignes : Alice (id=1) et Bob (id=2)
-- Claire et David exclus car présents dans les deux tables
-- ⚠️ L'ordre est asymétrique
SELECT id, nom, ville FROM clients_belgique
EXCEPT
SELECT id, nom, ville FROM clients_france;
-- Résultat différent : Emma (id=5) et Frank (id=6)
Compatibilité des opérateurs selon les SGBD
UNION et UNION ALL sont supportés universellement par tous les moteurs SQL. INTERSECT et EXCEPT sont supportés par PostgreSQL, SQL Server et Oracle, mais MySQL n’implémente INTERSECT et EXCEPT qu’à partir de la version 8.0.31. Sur les versions antérieures de MySQL, ces opérateurs doivent être simulés avec des JOIN ou des sous-requêtes.
-- Simulation de INTERSECT sur MySQL < 8.0.31
SELECT a.id, a.nom, a.ville
FROM clients_france a
INNER JOIN clients_belgique b
ON a.id = b.id AND a.nom = b.nom AND a.ville = b.ville;
-- Simulation de EXCEPT sur MySQL < 8.0.31
SELECT a.id, a.nom, a.ville
FROM clients_france a
LEFT JOIN clients_belgique b
ON a.id = b.id AND a.nom = b.nom AND a.ville = b.ville
WHERE b.id IS NULL;