DBAtlas · Atlas d'exploitation des bases de données

EXISTS / IN / NOT EXISTS (sous-requête)

Oracle

-- Customers with orders (EXISTS)
SELECT name FROM customer m
WHERE EXISTS (SELECT 1 FROM orders s WHERE s.customer_id = m.id);

-- List membership with IN
SELECT name FROM customer
WHERE city IN ('Ankara', 'Izmir');

-- Customers with no orders at all (NOT EXISTS)
SELECT name FROM customer m
WHERE NOT EXISTS (SELECT 1 FROM orders s WHERE s.customer_id = m.id);

EXISTS vérifie si une sous-requête corrélée renvoie au moins une ligne (il s'arrête à la première correspondance, donc rapide). IN vérifie si une valeur figure dans une liste/le résultat d'une sous-requête. Attention : si la sous-requête peut produire NULL, NOT IN donne des résultats inattendus ; NOT EXISTS est plus sûr. L'optimiseur Oracle transforme souvent les deux en un même plan.

PostgreSQL

SELECT name FROM customer m
WHERE EXISTS (SELECT 1 FROM orders s WHERE s.customer_id = m.id);

SELECT name FROM customer
WHERE city IN (SELECT city FROM target_cities);

SELECT name FROM customer m
WHERE NOT EXISTS (SELECT 1 FROM orders s WHERE s.customer_id = m.id);

PostgreSQL prend entièrement en charge EXISTS/IN/NOT EXISTS. Avec NOT IN, si la sous-requête contient NULL, tout le résultat peut devenir vide ; NOT EXISTS ou LEFT JOIN ... IS NULL est donc recommandé. Le planificateur traite IN et EXISTS de façon équivalente comme une semi-jointure dans la plupart des cas.

MySQL

SELECT name FROM customer m
WHERE EXISTS (SELECT 1 FROM orders s WHERE s.customer_id = m.id);

SELECT name FROM customer
WHERE city IN ('Ankara', 'Izmir');

SELECT name FROM customer m
WHERE NOT EXISTS (SELECT 1 FROM orders s WHERE s.customer_id = m.id);

MySQL/MariaDB prennent en charge EXISTS/IN/NOT EXISTS. Avant MySQL 5.6, les sous-requêtes corrélées pouvaient être lentes ; 5.6+ a accéléré les sous-requêtes IN grâce aux optimisations semi-join et materialization. Le piège NOT IN + NULL s'applique ici aussi.

SQL Server

SELECT name FROM customer m
WHERE EXISTS (SELECT 1 FROM orders s WHERE s.customer_id = m.id);

SELECT name FROM customer
WHERE city IN (SELECT city FROM target_cities);

SELECT name FROM customer m
WHERE NOT EXISTS (SELECT 1 FROM orders s WHERE s.customer_id = m.id);

SQL Server prend en charge EXISTS/IN/NOT EXISTS, et l'optimiseur les traite le plus souvent comme des semi/anti-jointures. Si une sous-requête NOT IN contient NULL, le résultat peut devenir vide de façon inattendue ; NOT EXISTS est le choix sûr. INTERSECT/EXCEPT peuvent aussi servir pour une logique d'appartenance similaire.

MongoDB

// IN equivalent: the $in operator
db.customer.find({ city: { $in: ["Ankara", "Izmir"] } })

// EXISTS equivalent: match check with $lookup + $match
db.customer.aggregate([
  { $lookup: { from: "orders", localField: "id",
      foreignField: "customer_id", as: "s" } },
  { $match: { "s.0": { $exists: true } } }  // at least one order
])

Dans MongoDB, l'appartenance à une liste de valeurs se fait avec les opérateurs $in / $nin. L'équivalent d'une sous-requête EXISTS consiste à récupérer le tableau des documents correspondants avec $lookup et à filtrer selon que le tableau est vide ou non. La vérification de l'existence d'un champ est un opérateur distinct { field: { $exists: true } } (présence d'un champ, pas relation entre lignes).

Redis

# Membership check with Set/Hash:
SISMEMBER target_cities "Ankara"   # is it in the set? (IN-like)
EXISTS customer:1                 # does the key exist?

Redis n'a pas de sous-requêtes. Pour l'appartenance d'une valeur, utilisez SISMEMBER sur un Set (de type IN). La commande EXISTS n'est pas une sous-requête ; elle indique si la clé donnée existe. Les vérifications d'existence relationnelles se font côté application en lisant plusieurs clés.

Elasticsearch

# IN equivalent: terms query
GET customer/_search
{ "query": { "terms": { "city": ["Ankara", "Izmir"] } } }

# Field existence: exists query
GET customer/_search
{ "query": { "exists": { "field": "phone" } } }

Dans Elasticsearch, l'équivalent de IN est la requête 'terms' (correspondance avec l'une de plusieurs valeurs), et NOT IN correspond à terms dans bool must_not. La requête 'exists' ne correspond pas au EXISTS SQL ; elle vérifie si un champ a une valeur dans le document. Un EXISTS corrélé entre tables nécessite généralement une dénormalisation.

Ouvrir dans DBAtlas →