Anti-jointures et semi-jointures (NOT EXISTS)
Trouvez les « lignes de A sans correspondance dans B » (anti-jointure) et les « lignes de A ayant au moins une correspondance dans B » (semi-jointure) avec EXISTS/NOT EXISTS.
Anti-jointures et semi-jointures (NOT EXISTS) est une leçon SQL Academy gratuite sur CoddyKit. Ceci est la leçon 3 sur 4. Tu peux lire la leçon complète ci-dessous gratuitement — puis la pratiquer en direct dans le navigateur avec un éditeur de code intégré et un tuteur IA 24/7. Elle fait partie du parcours d'apprentissage SQL Academy, et ta progression se synchronise sur le web et l'application CoddyKit. Le cours SQL Academy comprend 4 leçons au total.
Semi-jointure : « possède au moins une correspondance »
Renvoyez les lignes de A qui possèdent au moins une ligne correspondante dans B, mais uniquement les colonnes de A. SQL implémente les semi-jointures avec EXISTS ou IN.
Semi-jointure avec EXISTS
Utilisateurs ayant passé au moins une commande :
SELECT u.* FROM users u
WHERE EXISTS (
SELECT 1 FROM orders o WHERE o.user_id = u.id
);Semi-jointure avec IN
Même résultat, style différent :
SELECT * FROM users
WHERE id IN (SELECT user_id FROM orders);Pourquoi EXISTS est souvent plus performant
EXISTS s’arrête dès qu’il trouve une correspondance : il s’arrête à la première correspondance pour chaque ligne externe. IN peut matérialiser l’ensemble interne complet. Les planificateurs modernes optimisent souvent les deux vers le même plan, mais EXISTS est le choix le plus sûr pour les ensembles internes volumineux.
Anti-jointure : « ne possède aucune correspondance »
Utilisateurs n’ayant JAMAIS passé de commande — trois formes idiomatiques :
-- NOT EXISTS (preferred):
SELECT u.* FROM users u
WHERE NOT EXISTS (
SELECT 1 FROM orders o WHERE o.user_id = u.id
);
-- LEFT JOIN ... IS NULL:
SELECT u.* FROM users u
LEFT JOIN orders o ON o.user_id = u.id
WHERE o.id IS NULL;
-- NOT IN (risky with NULLs):
SELECT * FROM users WHERE id NOT IN (SELECT user_id FROM orders);Pourquoi NOT IN est risqué
Si la sous-requête interne contient NULL, NOT IN renvoie NULL, et WHERE élimine les lignes dont le prédicat vaut NULL. Résultat : aucune ligne. NOT EXISTS n’a pas ce problème.
Optimisation par le planificateur
Les versions modernes de PostgreSQL reconnaissent EXISTS et NOT EXISTS comme des modèles de semi-jointure ou d’anti-jointure et peuvent les exécuter avec des jointures par hachage :
EXPLAIN ANALYZE
SELECT u.* FROM users u
WHERE NOT EXISTS (SELECT 1 FROM orders o WHERE o.user_id = u.id);
-- → Hash Anti JoinAnti-jointures sur plusieurs colonnes
Utilisez des clés composites :
SELECT * FROM order_items oi
WHERE NOT EXISTS (
SELECT 1 FROM shipments s
WHERE s.order_id = oi.order_id
AND s.line_no = oi.line_no
);Semi-jointure avec EXISTS et prédicat supplémentaire
Ajoutez des filtres à la sous-requête interne :
SELECT u.* FROM users u
WHERE EXISTS (
SELECT 1 FROM orders o
WHERE o.user_id = u.id
AND o.status = 'paid'
AND o.created_at >= NOW() - INTERVAL '30 days'
);Indexer la colonne de corrélation
Avec EXISTS comme avec NOT EXISTS, la sous-requête interne filtre sur la clé de la ligne externe. Sans index sur cette clé, vous obtenez un parcours pour chaque ligne externe :
CREATE INDEX orders_user_id_idx ON orders(user_id);Quand utiliser LEFT JOIN ... IS NULL
Pour les tableaux de bord qui doivent également afficher les colonnes du côté sans correspondance, la forme LEFT JOIN est naturelle. Pour une sémantique d’anti-jointure pure, NOT EXISTS est plus clair.
Au-delà de SQL : les filtres de Bloom
Pour les anti-jointures très volumineuses, un préfiltre de type filtre de Bloom peut être utile. PostgreSQL prend en charge les index bloom via l’extension bloom.
Récapitulatif
Semi-jointure = « possède une correspondance » ; anti-jointure = « aucune correspondance ».
- EXISTS pour une semi-jointure
- NOT EXISTS pour une anti-jointure (compatible avec NULL)
- Indexez la colonne de corrélation
- Évitez NOT IN, sauf si l’ensemble interne ne peut pas contenir NULL
Vérification rapide
Vous voulez les utilisateurs qui n’ont JAMAIS passé de commande. Quelle solution SQL est la plus sûre et la plus idiomatique ?
Apprends SQL avec un tuteur IA — gratuit
Écris et exécute du vrai code dans ton navigateur, obtiens de l'aide instantanée d'un tuteur IA disponible 24h/24, et reprends là où tu t'es arrêté sur le web ou dans l'app.
- Cours
- 46
- Leçons
- 183
Questions Fréquemment Posées
La leçon « Anti-jointures et semi-jointures (NOT EXISTS) » est-elle gratuite ?
Oui — le texte complet de « Anti-jointures et semi-jointures (NOT EXISTS) » est gratuit à lire ici sur le web. Pour la pratiquer de manière interactive (un éditeur de code intégré et un tuteur IA 24/7) et déverrouiller le reste du cours SQL Academy, passe à CoddyKit PRO. Le cours SQL Academy comprend 4 leçons au total.
Qu'est-ce que j'apprendrai dans « Anti-jointures et semi-jointures (NOT EXISTS) » ?
Trouvez les « lignes de A sans correspondance dans B » (anti-jointure) et les « lignes de A ayant au moins une correspondance dans B » (semi-jointure) avec EXISTS/NOT EXISTS. Tu pratiques SQL Academy avec du code pratique que tu exécutes directement dans le navigateur, et un tuteur IA 24/7 répond à tes questions au fur et à mesure que tu avances dans la leçon.
Dois-je avoir de l'expérience pour commencer SQL Academy ?
Aucune expérience préalable n'est requise. SQL Academy sur CoddyKit est structuré pour les débutants jusqu'aux apprenants avancés, donc tu peux commencer ici ou depuis le début et avancer à ton rythme. Ceci est la leçon 3 sur 4.
Combien de temps prend la leçon « Anti-jointures et semi-jointures (NOT EXISTS) » ?
La plupart des leçons CoddyKit prennent environ 5–10 minutes. Chacune est courte et interactive, tu progresses régulièrement et tu repiques exactement où tu t'es arrêté sur le web et l'app.
Peux-tu écrire et exécuter du code dans cette leçon SQL Academy ?
Oui. Chaque leçon SQL Academy inclut un éditeur de code intégré, tu écris et exécutes du vrai code directement dans ton navigateur et tu reçois des retours IA instantanés — aucune configuration locale requise.
Toutes les leçons de ce cours
- Jointures croisées et produits cartésiens
- Jointures latérales (LATERAL JOIN)
- Anti-jointures et semi-jointures (NOT EXISTS)
- Optimisation des performances des jointures multi-tables