Question 1Lequel décrit correctement WHERE EXISTS (SELECT 1 FROM sales sale WHERE sale.emp_id = emp.emp_id) ?
EXISTS et sous-requêtes corrélées
Apprends EXISTS et les sous-requêtes corrélées en SQL : EXISTS / NOT EXISTS, comment éviter sûrement le piège NOT IN + NULL avec EXISTS, et quand préférer EXISTS à IN — pratiqué sur des données d'employés et de ventes, le tout s'exécutant en direct dans ton navigateur.
Données utilisées dans cet article — employee / sales / department
EXISTS est une sous-requête qui vérifie uniquement s'il existe au moins une ligne correspondante, et tu l'utilises un peu comme IN.
Dans cet article, tu vas parcourir les bases de EXISTS / NOT EXISTS, comment éviter sûrement le piège NOT IN + NULL en l'écrivant avec EXISTS, et comment choisir entre EXISTS et IN selon la lisibilité.
Le matériel est constitué de trois tables de données d'employés.
En utilisant employee (30 employés), sales (50 lignes de ventes) et department (6 services), tu vas extraire « les employés avec / sans ventes » et « les services sans employés ».
EXISTS / NOT EXISTS — vérifier seulement si une ligne existe
WHERE EXISTS (SELECT ... ) est vrai si la sous-requête renvoie ne serait-ce qu'une ligne, et faux si elle ne renvoie aucune ligne du tout.
Ce que la sous-requête sélectionne n'affecte pas le résultat, donc par convention tu écris SELECT 1 (la valeur n'est pas utilisée — seule compte l'existence d'une ligne).
La forme de base est une sous-requête corrélée qui référence une colonne de la requête principale à l'intérieur du EXISTS.
« Les employés avec des ventes » est WHERE EXISTS (SELECT 1 FROM sales sale WHERE sale.emp_id = emp.emp_id), et « les employés sans ventes » est la négation de cela, NOT EXISTS.
EXISTS arrête l'évaluation dès qu'il trouve une ligne, ce qui en fait un bon choix pour les tests d'existence.
-- EXISTS : employés avec des ventes
SELECT emp.emp_id, emp.name
FROM employee emp
WHERE EXISTS (
SELECT 1 FROM sales sale WHERE sale.emp_id = emp.emp_id
)
ORDER BY emp.emp_id;
Le piège NOT IN + NULL — EXISTS est sûr
Si tu écris un « filtrage négatif » avec NOT IN, le résultat peut revenir à 0 ligne quand un NULL se glisse du côté de la sous-requête.
x NOT IN (1, 2, NULL) est évalué comme « x n'est pas 1, pas 2, et pas NULL », mais x <> NULL ne devient jamais vrai et est toujours NULL (inconnu), donc le NOT IN entier ne devient jamais vrai.
Le raisonnement complet est expliqué dans Sous-requêtes ① (le piège NOT IN + NULL).
Comme employee.dept_id mêle des NULL, écrire « les services sans employés » sous la forme WHERE dept_id NOT IN (SELECT dept_id FROM employee) fait disparaître Legal (un service sans aucun employé), qui devrait pourtant être là, et le résultat revient à 0 ligne.
NOT EXISTS regarde uniquement si une ligne existe et n'est pas affecté par NULL, donc dans cette situation NOT EXISTS renvoie le résultat correct.
-- Piège : une sous-requête contenant NULL + NOT IN revient à 0 ligne
SELECT dept_id, dept_name
FROM department
WHERE dept_id NOT IN (SELECT dept_id FROM employee);
-- → 0 ligne car employee.dept_id contient NULL
-- Sûr : NOT EXISTS n'est pas affecté par NULL
SELECT d.dept_id, d.dept_name
FROM department d
WHERE NOT EXISTS (
SELECT 1 FROM employee emp WHERE emp.dept_id = d.dept_id
);
Choisis EXISTS selon la lisibilité
EXISTS regarde uniquement si une ligne existe, donc il est sûr même en présence de NULL, mais écrire une sous-requête corrélée peut le faire paraître plus long que IN.
Pour un simple test d'existence, il y a des situations où IN se lit mieux, et en pratique tu choisis selon le contexte.
En revanche, pour une négation comme NOT IN où NULL casse le résultat, ou quand tu veux juger de façon fiable seulement si une ligne existe, EXISTS / NOT EXISTS est le choix sûr.
Vérification des connaissances
Répondez à chaque question une par une.
Question 2Quand un NULL peut se glisser du côté de la sous-requête, quel problème peut survenir si tu écris un filtrage négatif avec NOT IN ?
Question 3Quelle est une façon appropriée de choisir entre EXISTS et IN ?