DBAtlas · Atlas für Datenbankbetrieb

EXISTS / IN / NOT EXISTS (Unterabfrage)

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 prüft, ob eine korrelierte Unterabfrage mindestens eine Zeile liefert (stoppt beim ersten Treffer und ist daher schnell). IN prüft, ob ein Wert in einer Liste/einem Unterabfrageergebnis enthalten ist. Achtung: Kann die Unterabfrage NULL liefern, ergibt NOT IN unerwartete Ergebnisse; NOT EXISTS ist sicherer. Der Oracle-Optimizer macht aus beiden oft denselben 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 unterstützt EXISTS/IN/NOT EXISTS vollständig. Enthält bei NOT IN die Unterabfrage NULL, kann das gesamte Ergebnis leer werden; daher werden NOT EXISTS oder LEFT JOIN ... IS NULL empfohlen. Der Planner behandelt IN und EXISTS in den meisten Fällen gleichwertig als Semi-Join.

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 unterstützen EXISTS/IN/NOT EXISTS. Vor MySQL 5.6 konnten korrelierte Unterabfragen langsam sein; ab 5.6 wurden IN-Unterabfragen durch Semi-Join- und Materialisierungsoptimierungen beschleunigt. Die Falle NOT IN + NULL gilt auch hier.

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 unterstützt EXISTS/IN/NOT EXISTS, und der Optimizer verarbeitet sie meist als Semi-/Anti-Joins. Enthält eine NOT IN-Unterabfrage NULL, kann das Ergebnis unerwartet leer werden; NOT EXISTS ist die sichere Wahl. Für ähnliche Mitgliedschaftslogik lassen sich auch INTERSECT/EXCEPT nutzen.

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
])

In MongoDB erfolgt die Mitgliedschaftsprüfung in Wertelisten mit den Operatoren $in / $nin. Die Entsprechung zu EXISTS mit Unterabfrage ist, mit $lookup das Array passender Dokumente zu holen und danach zu filtern, ob das Array leer ist. Die Prüfung auf Feldexistenz ist ein separater Operator { field: { $exists: true } } (das Vorhandensein eines Felds, keine Zeilenbeziehung).

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 hat keine Unterabfragen. Für die Mitgliedschaftsprüfung nutze SISMEMBER auf einem Set (IN-ähnlich). Der Befehl EXISTS ist keine Unterabfrage; er liefert, ob der angegebene Schlüssel existiert. Relationale Existenzprüfungen erfolgen in der Anwendung durch Lesen mehrerer Schlüssel.

Elasticsearch

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

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

In Elasticsearch entspricht die 'terms'-Abfrage IN (Treffer auf einen von mehreren Werten), NOT IN ist terms innerhalb von bool must_not. Die 'exists'-Abfrage entspricht nicht SQL-EXISTS; sie prüft, ob ein Feld im Dokument einen Wert hat. Tabellenübergreifendes korreliertes EXISTS erfordert meist Denormalisierung.

In DBAtlas öffnen →