DBAtlas · Atlas für Datenbankbetrieb

LATERAL / CROSS APPLY (zeilenweise Unterabfrage)

Oracle

-- Each customer's 3 most recent orders (LATERAL, 12c+)
SELECT m.name, s.created_at, s.amount
FROM customer m,
     LATERAL (SELECT created_at, amount FROM orders
              WHERE customer_id = m.id
              ORDER BY created_at DESC FETCH FIRST 3 ROWS ONLY) s;

-- Alternative: CROSS APPLY (12c+)
SELECT m.name, s.amount
FROM customer m
CROSS APPLY (SELECT amount FROM orders WHERE customer_id = m.id) s;

LATERAL/APPLY erlaubt einer Unterabfrage in FROM, auf Spalten der links davon stehenden Tabelle zu verweisen, sodass du korrelierte Joins wie 'die ersten N Zeilen für jede Zeile' schreiben kannst. Oracle 12c unterstützt sowohl ANSI-LATERAL als auch die Syntax CROSS/OUTER APPLY.

PostgreSQL

SELECT m.name, s.created_at, s.amount
FROM customer m
CROSS JOIN LATERAL (
  SELECT created_at, amount FROM orders
  WHERE customer_id = m.id
  ORDER BY created_at DESC LIMIT 3
) s;

In PostgreSQL werden Unterabfragen, die von der Zeile links davon abhängen, mit dem Schlüsselwort LATERAL geschrieben (JOIN LATERAL / CROSS JOIN LATERAL / LEFT JOIN LATERAL). Sehr praktisch für 'Top N pro Gruppe' und zum Expandieren von Zeilen mit Set-Returning Functions. Eine CROSS APPLY-Syntax gibt es nicht; es wird LATERAL verwendet.

MySQL

-- MySQL 8.0.14+ supports LATERAL
SELECT m.name, s.amount
FROM customer m
JOIN LATERAL (
  SELECT amount FROM orders
  WHERE customer_id = m.id
  ORDER BY created_at DESC LIMIT 3
) s ON true;

Seit MySQL 8.0.14 werden LATERAL Derived Tables unterstützt; die Unterabfrage kann auf Spalten der äußeren Tabelle verweisen. Davor und für CROSS APPLY gab es keine Entsprechung; 'Top N pro Gruppe' wurde mit Fensterfunktionen oder korrelierten Unterabfragen gelöst. MariaDB hat noch kein LATERAL.

SQL Server

SELECT m.name, s.created_at, s.amount
FROM customer m
CROSS APPLY (
  SELECT TOP 3 created_at, amount FROM orders
  WHERE customer_id = m.id
  ORDER BY created_at DESC
) s;
-- Use OUTER APPLY to return non-matching rows too

In SQL Server entspricht der APPLY-Operator LATERAL: CROSS APPLY (wie INNER JOIN LATERAL, verwirft Nicht-Treffer) und OUTER APPLY (wie LEFT JOIN LATERAL, NULL bei Nicht-Treffern). Üblich, um für jede Zeile Table-Valued Functions aufzurufen, und für Top-N-pro-Gruppe-Abfragen.

MongoDB

// Closest equivalent: $lookup with a sub-pipeline
db.customer.aggregate([
  { $lookup: {
      from: "orders",
      let: { mid: "$id" },
      pipeline: [
        { $match: { $expr: { $eq: ["$customer_id", "$$mid"] } } },
        { $sort: { created_at: -1 } }, { $limit: 3 }
      ],
      as: "last3"
  } }
])

In MongoDB entspricht LATERAL/APPLY die $lookup-Form mit Sub-Pipeline und let-Variablen: Die Felder des äußeren Dokuments werden über let als $$variable an die Sub-Pipeline übergeben, wo Abgleich/Sortierung/Begrenzung erfolgen. Damit wird das Muster 'zugehörige Top N für jedes Dokument' gelöst.

Redis

# Not applicable: Redis has no subqueries / LATERAL.

Redis bietet keine zeilenweise korrelierten Unterabfragen. Das Muster 'zugehörige Top N für jedes Element' wird mit einer Schleife in der Anwendung gelöst (z. B. ein separates ZRANGE pro Schlüssel) oder mit einem serverseitigen Lua-Skript.

Elasticsearch

# Closest equivalent: terms + top_hits sub-aggregation
GET orders/_search
{
  "size": 0,
  "aggs": { "by_customer": { "terms": { "field": "customer_id" },
    "aggs": { "last3": { "top_hits": {
      "sort": [ { "created_at": "desc" } ], "size": 3 } } } } }
}

Elasticsearch hat kein LATERAL/APPLY; das Muster 'Top-N-Datensätze pro Gruppe' wird mit einer in eine terms-Aggregation verschachtelten Sub-Aggregation top_hits erreicht. Statt einer korrelierten Unterabfrage ist dies Gruppierung plus Stichprobe innerhalb der Gruppe auf einem einzelnen Index.

In DBAtlas öffnen →