EXISTS et NOT EXISTS corrélés
L’alternative robuste à la jointure anti, qui gère correctement les NULL
EXISTS et NOT EXISTS corrélés est une leçon Coding Interview Prep 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 Coding Interview Prep, et ta progression se synchronise sur le web et l'application CoddyKit. Le cours Coding Interview Prep comprend 4 leçons au total.
EXISTS vérifie la présence
EXISTS prend une sous-requête et renvoie TRUE dès que cette sous-requête produit au moins une ligne, et FALSE dans le cas contraire. Il ne renvoie jamais les lignes elles-mêmes.
Avec une sous-requête corrélée à l’intérieur, EXISTS devient une vérification de présence pour chaque ligne externe : « existe-t-il une ligne correspondante pour cette ligne externe ? »
Comme il s’arrête dès la première correspondance, il ne tient pas compte du nombre de lignes correspondantes. Ce détail de sémantique est très apprécié en entretien.
Un EXISTS corrélé élémentaire
Recherchez les clients qui ont passé au moins une commande. La requête interne est corrélée par l’intermédiaire de o.customer_id = c.customer_id.
Pour chaque client, EXISTS pose la question suivante : existe-t-il une commande pour ce client ? Si oui, conservez le client.
SELECT c.customer_id, c.name
FROM customers c
WHERE EXISTS (
SELECT 1
FROM orders o
WHERE o.customer_id = c.customer_id
);Pourquoi utiliser SELECT 1 dans EXISTS
À l’intérieur de EXISTS, vous verrez SELECT 1, SELECT * ou SELECT NULL. Ces trois formes sont équivalentes.
EXISTS vérifie seulement si des lignes sont renvoyées, jamais leur contenu ; les colonnes sélectionnées n’ont donc aucune importance. L’optimiseur les ignore.
SELECT 1 est une convention courante qui indique l’intention : « je m’intéresse uniquement à l’existence. » Choisissez-en une et restez cohérent ; ne laissez pas la personne qui mène l’entretien penser que la liste de colonnes a de l’importance ici.
NOT EXISTS trouve les absences
NOT EXISTS inverse la vérification : ne conservez la ligne externe que lorsque la sous-requête corrélée ne renvoie aucune ligne.
C’est l’anti-jointure classique : les clients sans commande, les produits jamais vendus, les étudiants n’ayant remis aucun travail.
SELECT c.customer_id, c.name
FROM customers c
WHERE NOT EXISTS (
SELECT 1
FROM orders o
WHERE o.customer_id = c.customer_id
);Le piège des NULL avec NOT IN
Voici le point qui fait mouche en entretien. NOT IN face à une sous-requête pouvant contenir NULL se comporte de manière piégeuse : si la liste contient ne serait-ce qu’un NULL, NOT IN ne renvoie aucune ligne.
Cela se produit car une comparaison avec NULL donne UNKNOWN, et NOT IN exige que chaque comparaison soit fausse. Un seul UNKNOWN contamine toute la condition.
NOT EXISTS n’a pas ce problème ; il vérifie simplement la présence de lignes et gère correctement les NULL.
-- Risky: returns nothing if any o.customer_id is NULL
SELECT c.customer_id FROM customers c
WHERE c.customer_id NOT IN (SELECT o.customer_id FROM orders o);
-- Safe: NULLs do not break it
SELECT c.customer_id FROM customers c
WHERE NOT EXISTS (
SELECT 1 FROM orders o WHERE o.customer_id = c.customer_id
);Pourquoi NOT EXISTS gère les NULL correctement
La raison se trouve dans la logique de correspondance. NOT EXISTS vérifie si une ligne interne satisfait o.customer_id = c.customer_id.
Une ligne dont o.customer_id vaut NULL ne satisfait jamais cette égalité (NULL = n’importe quoi donne UNKNOWN et non TRUE) ; elle ne compte donc simplement pas comme une correspondance. La vérification de présence reste correcte.
Avec NOT IN, ce même NULL devient partie intégrante d’une comparaison avec une liste, dont le résultat UNKNOWN supprime toute la sortie. C’est pourquoi, lors des entretiens techniques senior, on préfère NOT EXISTS.
EXISTS avec des conditions supplémentaires
La sous-requête corrélée peut contenir davantage de prédicats. Trouvez les clients qui ont passé au moins une commande supérieure à 1000.
La condition supplémentaire se trouve dans la sous-requête EXISTS, avec une portée définie pour chaque client.
SELECT c.customer_id, c.name
FROM customers c
WHERE EXISTS (
SELECT 1
FROM orders o
WHERE o.customer_id = c.customer_id
AND o.amount > 1000
);Performances : comportement de court-circuit
EXISTS peut arrêter l’analyse de la relation interne dès qu’une ligne correspondante est trouvée. Il ne construit ni ne dénombre un jeu de résultats complet.
Cela rend EXISTS généralement efficace, surtout lorsque la colonne corrélée est indexée, car chaque recherche ligne par ligne peut trouver rapidement une correspondance et s’arrêter.
Comparez cela à un COUNT(*) > 0 corrélé, qui oblige à compter toutes les correspondances. Préférez EXISTS lorsque vous avez uniquement besoin d’une réponse oui/non.
EXISTS ou COUNT pour tester la présence
Les candidats écrivent parfois un décompte corrélé pour tester la présence. Cela fonctionne, mais demande des efforts inutiles.
La version COUNT dénombre chaque commande correspondante ; EXISTS s’arrête après la première. Pour un simple test d’existence, EXISTS exprime clairement l’intention et permet à l’optimiseur de s’arrêter dès que possible.
-- Works but counts everything
SELECT c.customer_id FROM customers c
WHERE (SELECT COUNT(*) FROM orders o
WHERE o.customer_id = c.customer_id) > 0;
-- Better: stops at first match
SELECT c.customer_id FROM customers c
WHERE EXISTS (SELECT 1 FROM orders o
WHERE o.customer_id = c.customer_id);Exemple détaillé : produits jamais commandés
Une question classique d’entretien sur l’anti-jointure consiste à lister les produits qui n’ont jamais été commandés. NOT EXISTS se lit presque comme l’exigence formulée en anglais.
Pour chaque produit, vérifiez si une ligne de commande le référence ; ne gardez que ceux pour lesquels ce n’est pas le cas.
SELECT p.product_id, p.name
FROM products p
WHERE NOT EXISTS (
SELECT 1
FROM order_items oi
WHERE oi.product_id = p.product_id
);EXISTS dans NOT EXISTS pour les requêtes de type division
Imbriquer EXISTS dans NOT EXISTS exprime une division relationnelle : « trouver les lignes qui correspondent à ALL les éléments d’un ensemble » Une question classique consiste à trouver les clients qui ont commandé chaque produit d’une catégorie.
La logique est la suivante : conservez un client lorsqu’il n’existe aucun produit qu’il n’a pas commandé. Cette double négation caractérise les requêtes de division, et les personnes qui vous interrogent l’utilisent pour vérifier votre maîtrise approfondie de EXISTS.
SELECT c.customer_id
FROM customers c
WHERE NOT EXISTS (
SELECT 1 FROM products p
WHERE p.category = 'Coffee'
AND NOT EXISTS (
SELECT 1 FROM order_items oi
JOIN orders o ON o.order_id = oi.order_id
WHERE oi.product_id = p.product_id
AND o.customer_id = c.customer_id
)
);Vérification rapide
Choisissez la méthode la plus sûre pour trouver les clients sans commande.
Récapitulatif : EXISTS et NOT EXISTS corrélés
Points essentiels :
EXISTSest un test de présence effectué pour chaque ligne, qui s’arrête à la première correspondance ; le choix de la colonne à l’intérieur est sans importance (utilisezSELECT 1).NOT EXISTSest l’anti-jointure qui gère NULL sans ambiguïté pour trouver les lignes sans correspondance.NOT INavec un NULL dans la liste ne renvoie rien ; préférezNOT EXISTS.- Pour tester l’existence, EXISTS est préférable à un
COUNT(*) > 0corrélé, car il s’arrête rapidement.
Mentionnez spontanément le piège de NULL avec NOT IN ; c’est un indicateur fiable de maturité en SQL.
Questions Fréquemment Posées
La leçon « EXISTS et NOT EXISTS corrélés » est-elle gratuite ?
Oui — le texte complet de « EXISTS et NOT EXISTS corrélés » 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 Coding Interview Prep, passe à CoddyKit PRO. Le cours Coding Interview Prep comprend 4 leçons au total.
Qu'est-ce que j'apprendrai dans « EXISTS et NOT EXISTS corrélés » ?
L’alternative robuste à la jointure anti, qui gère correctement les NULL Tu pratiques Coding Interview Prep 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 Coding Interview Prep ?
Aucune expérience préalable n'est requise. Coding Interview Prep 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 « EXISTS et NOT EXISTS corrélés » ?
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 Coding Interview Prep ?
Oui. Chaque leçon Coding Interview Prep 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
- Anatomie d’une sous-requête corrélée
- Agrégats par groupe sans GROUP BY
- EXISTS et NOT EXISTS corrélés
- Réécrire les sous-requêtes corrélées avec des jointures