カテゴリ:

クエリ構文

ラテラル結合

FROM 句では、 LATERAL キーワードを使用すると、インラインビューでそのインラインビューの前にあるテーブル式から列を参照できます。

ラテラル結合は、ほとんどの JOINs よりも相関サブクエリのように動作します。ラテラル結合は、サーバーが次のようなループを実行したかのように動作します。

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

非ラテラル結合の出力とは異なり、ラテラル結合の出力には、インラインビューから生成された行のみが含まれます。左側の行は、インラインビューに渡されることで既に考慮されているため、左側の行を右側に結合する必要はありません。

このトピックの内容:

構文

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

これは、次のような行のソースです。

  • テーブル。

  • ビュー。

  • サブクエリ。

  • テーブル関数。

  • 以前の結合の結果。

inline_view

inline_view は次のいずれかです。

  • インラインビュー(ステートメント内で定義され、ステートメントの期間のみ有効なビュー)。

  • サブクエリ。

  • テーブル関数( FLATTEN などの組み込みテーブル関数、またはユーザー定義のテーブル関数(UDTF)のいずれか)。

inline_view はテーブルにできません。

使用上の注意

  • キーワード LATERAL の後のインラインビューは、インラインビュー自体および FROM 句のインラインビューの左側のテーブルからのみ列を参照できます。

    SELECT *
        FROM table_reference_me, LATERAL (...), table_do_not_reference_me ...
    
    Copy
  • 通常、インラインビューは left_hand_table_expression の列を参照しますが、必ずしもそうする必要はありません。

  • INNER JOIN 構文がコンマまたは単語「INNER JOIN」を使用できるように、ラテラル結合でもコンマまたは単語 INNER JOIN を使用できます。

  • ラテラルテーブル関数(SQL UDTF 以外)では、 ON、 USING、 NATURAL JOIN 句は指定できません。また、テーブル関数(SQL UDTF 以外)への外側ラテラル結合では、 ON、 USING、 NATURAL JOIN 句は指定できません。

    詳細については、 JOIN トピックにある使用上の注意 をご参照ください。

この例では、次のデータを使用します。

CREATE TABLE departments (department_id INTEGER, name VARCHAR);
CREATE TABLE employees (employee_ID INTEGER, last_name VARCHAR, 
                        department_ID INTEGER, project_names ARRAY);
Copy
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

基本的な例

この例は、サブクエリを持つ LATERAL JOIN を示しています。

SELECT * 
    FROM departments AS d, LATERAL (SELECT * FROM employees AS e WHERE e.department_ID = d.department_ID) AS iv2
    ORDER BY employee_ID;
+---------------+-------------+-------------+-----------+---------------+---------------+
| 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          |
+---------------+-------------+-------------+-----------+---------------+---------------+
Copy

FLATTEN()で LATERAL を使用する例

この例は、ラテラル結合が FLATTEN によって返されるインラインビューをどのように使用できるかを示しています。

SELECT * FROM table1, LATERAL FLATTEN(...);
Copy

まず、従業員テーブルを更新して、 FLATTEN が操作できる ARRAY データを含めます。

UPDATE employees SET project_names = ARRAY_CONSTRUCT('Materialized Views', 'UDFs') 
    WHERE employee_ID = 101;
UPDATE employees SET project_names = ARRAY_CONSTRUCT('Materialized Views', 'Lateral Joins')
    WHERE employee_ID = 102;
Copy

次に、 FLATTEN を使用し、その前にあるテーブルの列への参照を含むクエリを実行します。

SELECT emp.employee_ID, emp.last_name, index, value AS project_name
    FROM employees AS emp, LATERAL FLATTEN(INPUT => emp.project_names) AS proj_names
    ORDER BY employee_ID;
+-------------+-----------+-------+----------------------+
| EMPLOYEE_ID | LAST_NAME | INDEX | PROJECT_NAME         |
|-------------+-----------+-------+----------------------|
|         101 | Richards  |     0 | "Materialized Views" |
|         101 | Richards  |     1 | "UDFs"               |
|         102 | Paulson   |     0 | "Materialized Views" |
|         102 | Paulson   |     1 | "Lateral Joins"      |
+-------------+-----------+-------+----------------------+
Copy

両方の結合構文を示す例

次の SQL ステートメントは同等であり、同じ出力を生成します(出力は以下に1度だけ示されています)。以下の最初の SQL ステートメントは、キーワード LATERAL の前にコンマを使用していますが、2番目の SQL ステートメントは、キーワード INNER JOIN を使用しています。

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
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;
+---------------+-------------+-------------+-----------+---------------+---------------+
| 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          |
+---------------+-------------+-------------+-----------+---------------+---------------+
Copy