Kategorien:

Abfragesyntax

LATERAL

In einer FROM-Klausel ermöglicht das LATERAL-Schlüsselwort einer Inline-Ansicht, auf Spalten aus einem Tabellenausdruck zu verweisen, der dieser Inline-Ansicht vorausgeht.

A lateral join behaves more like a correlated subquery than a typical join. A lateral join behaves as if the server executed a loop similar to the following:

for each row in left_hand_table LHT:
    execute right_hand_subquery RHS using the values from the current row in the LHT
Copy

Unlike the output of a non-lateral join, the output from a lateral join includes only the rows generated from the inline view. There is no need for an explicit ON clause to join rows from the left-hand side to the right-hand side; the relationship is already established because the inline view references columns from the left-hand table expression.

Siehe auch Seitliche Verknüpfungen verwenden.

Wann wird LATERAL verwendet?

LATERAL ist ein nützliches Tool für die folgenden Anwendungsfälle:

  • Verketten von Tabellenfunktionen für verschachtelte Daten: Wenn Sie Arrays innerhalb von Arrays vereinfachen oder auf mehreren Ebenen von verschachtelten JSONs navigieren müssen, muss jeder nachfolgende Tabellenfunktionsaufruf auf die Ausgabe des vorherigen verweisen. Laterale Joins machen dies möglich.

  • Aufrufen von Tabellenfunktionen mit zeilenspezifischen Argumenten: Wenn eine Tabellenfunktion (wie UDTF) andere Eingabewerte für jede Zeile von der linken Tabelle erhalten muss.

Für einfache Fälle, wie z. B. das Vereinfachen eines Arrays mit einer Ebene, liefert die Verwendung von TABLE(FLATTEN(...)) ohne lateralen Join das gleiche Ergebnis. Laterale Joins sind nur dann notwendig, wenn die Inline-Ansicht auf Spalten verweisen muss, die nur über einen vorangehenden Ausdruck in der FROM-Klausel verfügbar sind.

Syntax

SELECT ...
  FROM <left_hand_table_expression>, LATERAL ( <inline_view> )
...
Copy

Parameter

left_hand_table_expression

Dies ist eine Quelle für Zeilen wie:

  • Eine Tabelle

  • Eine Ansicht

  • Eine Unterabfrage

  • Eine Tabellenfunktion

  • Das Ergebnis eines früheren Join

inline_view

Die inline_view kann sein:

  • Eine Inline-Ansicht: eine in der Anweisung definierte Ansicht, die nur für die Dauer der Anweisung gültig ist.

  • Eine Unterabfrage

  • Eine Tabellenfunktion: entweder eine integrierte Tabellenfunktion wie FLATTEN oder eine benutzerdefinierte Tabellenfunktion (UDTF).

Die inline_view kann keine einfache Tabellenreferenz sein. Es muss sich um einen Ausdruck handeln, der Zeilen auf Basis von Werten aus dem linken Tabellenausdruck verarbeiten oder filtern kann, z. B. eine Unterabfrage mit einer WHERE-Klausel oder ein Tabellenfunktionsaufruf.

Nutzungshinweise

  • Die Inline-Ansicht nach dem Schlüsselwort LATERAL kann nur auf Spalten in der Inline-Ansicht selbst und in Tabellen links von der Inline-Ansicht in der FROM-Klausel verweisen.

    SELECT *
      FROM table_reference_me, LATERAL (...), table_do_not_reference_me ...
    
    Copy
  • Although the inline view typically references one or more columns from the left_hand_table_expression, it is not required to do so.

  • So wie bei der INNER JOIN-Syntax entweder das Komma oder die Schlüsselwörter INNER JOIN verwendet werden können, können bei einem lateralen Join ebenfalls das Komma oder die Schlüsselwörter INNER JOIN verwendet werden. Beispiel:

    FROM departments AS d INNER JOIN LATERAL (...)
    
    Copy
  • Die ON-, USING- oder NATURAL JOIN-Klausel kann nicht angegeben werden in:

    • einer lateralen Tabellenfunktion (außer SQL UDTF)

    • einem äußeren lateralen Join zu einer Tabellenfunktion (außer SQL UDTF)

    For details, see the usage notes in the JOIN topic.

Beispiele

Siehe auch Beispiel: Verwendung einer Lateral Join mit der Tabellenfunktion FLATTEN und Verwenden von FLATTEN zum Filtern der Ergebnisse in einer WHERE-Klausel.

Das folgende Beispiel verwendet diese Tabellen:

CREATE TABLE departments (department_id INTEGER, name VARCHAR);
CREATE TABLE employees (employee_ID INTEGER, last_name VARCHAR,
  department_ID INTEGER, project_names ARRAY);

INSERT INTO departments (department_ID, name) VALUES
  (1, 'Engineering'),
  (2, 'Support');
INSERT INTO employees (employee_ID, last_name, department_ID) VALUES
  (101, 'Richards', 1),
  (102, 'Paulson',  1),
  (103, 'Johnson',  2);
Copy

Diese folgende Abfrage ist ein lateraler Join mit einer Unterabfrage.

SELECT *
  FROM departments AS d,
    LATERAL (SELECT * FROM employees AS e WHERE e.department_ID = d.department_ID) AS iv2
  ORDER BY employee_ID;
Copy
+---------------+-------------+-------------+-----------+---------------+---------------+
| DEPARTMENT_ID | NAME        | EMPLOYEE_ID | LAST_NAME | DEPARTMENT_ID | PROJECT_NAMES |
|---------------+-------------+-------------+-----------+---------------+---------------|
|             1 | Engineering |         101 | Richards  |             1 | NULL          |
|             1 | Engineering |         102 | Paulson   |             1 | NULL          |
|             2 | Support     |         103 | Johnson   |             2 | NULL          |
+---------------+-------------+-------------+-----------+---------------+---------------+

Die folgende SQL-Anweisung ist gleichwertig und erzeugt die gleiche Ausgabe. Sie verwendet die Schlüsselwörter INNER JOIN anstelle des Kommas in der FROM-Klausel.

SELECT *
  FROM departments AS d INNER JOIN
    LATERAL (SELECT * FROM employees AS e WHERE e.department_ID = d.department_ID) AS iv2
  ORDER BY employee_ID;
Copy

Verketten von LATERAL FLATTEN für verschachtelte Daten

LATERAL ist erforderlich, wenn Sie mehrere FLATTEN-Aufrufe für den Zugriff auf verschachtelte Datenstrukturen verketten müssen. Im folgenden Beispiel muss das zweite FLATTEN auf die Ausgabe des ersten FLATTEN verweisen, was nur mit LATERAL möglich ist.

CREATE OR REPLACE TABLE persons AS
  SELECT column1 AS id, PARSE_JSON(column2) AS c
    FROM VALUES
      (12712555,
       '{ "name": { "first": "John", "last": "Smith" },
          "contact": [{ "business": [
            { "type": "phone", "content": "555-1234" },
            { "type": "email", "content": "j.smith@example.com" }
          ]}]}'),
      (98127771,
       '{ "name": { "first": "Jane", "last": "Doe" },
          "contact": [{ "business": [
            { "type": "phone", "content": "555-1236" },
            { "type": "email", "content": "j.doe@example.com" }
          ]}]}');
Copy

Die folgende Abfrage verwendet zwei LATERAL FLATTEN-Aufrufe. Beim ersten Aufruf wird das contact-Array vereinfacht, und der zweite vereinfacht das business-Array innerhalb jedes Kontakts. Der zweite FLATTEN-Aufruf referenziert f.value, der aus der Ausgabe des ersten FLATTEN-Aufruf stammt.

SELECT id,
    f1.value:type::STRING AS contact_type,
    f1.value:content::STRING AS contact_details
  FROM persons p,
    LATERAL FLATTEN(INPUT => p.c, PATH => 'contact') f,
    LATERAL FLATTEN(INPUT => f.value:business) f1;
Copy
+----------+--------------+---------------------+
|       ID | CONTACT_TYPE | CONTACT_DETAILS     |
|----------+--------------+---------------------|
| 12712555 | phone        | 555-1234            |
| 12712555 | email        | j.smith@example.com |
| 98127771 | phone        | 555-1236            |
| 98127771 | email        | j.doe@example.com   |
+----------+--------------+---------------------+

Diese Abfrage kann nicht ohne LATERAL geschrieben werden, da der zweite FLATTEN-Aufruf von der Ausgabe des ersten ab FLATTEN-Aufrufs abhängt.

LATERAL im Vergleich zu anderen Ansätzen

Die folgende Tabelle fasst zusammen, wann LATERAL im Vergleich zu anderen Ansätzen verwendet werden sollte:

Anwendungsfall

Empfehlung

Vereinfachen eines einstufigen Arrays

TABLE(FLATTEN(...)) ohne LATERAL funktioniert genauso. LATERAL ist optional.

Vereinfachen verschachtelter Arrays (Arrays innerhalb von Arrays)

LATERAL muss FLATTEN-Aufrufe verketten.

Filtern von Zeilen aus einer anderen Tabelle auf Basis der aktuellen Zeile

Es funktioniert entweder eine korrelierte Unterabfrage in der SELECT-Liste oder LATERAL. LATERAL kann mehrere Zeilen und Spalten zurückgeben. Eine korrelierte Abfrage in SELECT ist dazu nicht in der Lage.

Aufrufen einer Tabellenfunktion mit zeilenspezifischer Eingabe

LATERAL ermöglicht es der Tabellenfunktion, verschiedene Argumente für die einzelnen Zeilen zu erhalten.