IN teste si une valeur appartient à l'ensemble renvoyé par une sous-requête, EXISTS teste si la sous-requête renvoie au moins une ligne. EXISTS s'arrête à la première ligne trouvée et gère bien les NULL, ce qui le rend plus sûr que NOT IN pour exprimer une absence.
Exemple
WHERE EXISTS (SELECT 1 FROM commandes o WHERE o.client_id = c.id)