카테고리:

쿼리 구문

LATERAL

FROM 절에서 LATERAL 키워드를 사용하면 인라인 뷰가 해당 인라인 뷰에 선행하는 테이블 식의 열을 참조할 수 있습니다.

래터럴 조인은 일반적인 조인보다 상관 하위 쿼리처럼 동작합니다. 래터럴 조인은 서버가 다음과 유사한 루프를 실행한 것처럼 동작합니다.

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

비측면 조인의 출력과 달리, 측면 조인의 출력에는 인라인 뷰에서 생성된 행만 포함됩니다. 왼쪽에서 오른쪽으로 행을 조인하기 위해 명시적 ON 절이 필요하지 않으며, 인라인 뷰가 왼쪽 테이블 식의 열을 참조하므로 관계가 이미 설정되어 있습니다.

참고 항목: 측면 조인 사용하기.

LATERAL 사용 시점

LATERAL은 다음 사용 사례에 유용한 도구입니다.

  • 중첩 데이터에 대한 테이블 함수 연결하기: 배열 내에서 배열을 평면화하거나 여러 수준의 중첩된 JSON을 탐색해야 하는 경우, 각 후속 테이블 함수 호출은 이전 함수 호출의 출력을 참조해야 합니다. 측면 조인은 이를 가능하게 합니다.

  • 행별 인자로 테이블 함수 호출하기: 테이블 함수(예: UDTF)는 왼쪽 테이블에서 각 행에 대해 다른 입력 값을 수신해야 합니다.

단일 수준 배열 평면화와 같이 간단한 작업의 경우 측면 조인이 없는 :code:`TABLE(FLATTEN(…))`을 사용하여 동일한 결과를 생성합니다. 측면 조인은 인라인 뷰가 FROM 절의 이전 식에서만 사용할 수 있는 열을 참조해야 하는 경우에만 필요합니다.

구문

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

매개 변수

left_hand_table_expression

이는 다음과 같은 행 소스입니다.

  • 테이블.

  • 뷰.

  • 하위 쿼리.

  • 테이블 함수.

  • 이전 조인의 결과입니다.

inline_view

inline_view 는 다음과 같을 수 있습니다:

  • 인라인 뷰: 문 내에서 정의되고 문의 기간 동안에만 유효한 뷰.

  • 하위 쿼리.

  • 테이블 함수: FLATTEN 과 같은 기본 제공 테이블 함수 또는 사용자 정의 테이블 함수(UDTF).

:samp:`{inline_view}`는 일반 테이블 참조가 될 수 없습니다. WHERE 절 또는 테이블 함수 호출이 있는 하위 쿼리와 같이 왼쪽 테이블 식의 값을 기반으로 행을 처리하거나 필터링할 수 있는 식이어야 합니다.

사용법 노트

  • LATERAL 키워드 뒤의 인라인 뷰는 인라인 뷰 자체에서만, 그리고 FROM 절의 인라인 뷰 왼쪽에 있는 테이블에서만 열을 참조할 수 있습니다.

    SELECT *
      FROM table_reference_me, LATERAL (...), table_do_not_reference_me ...
    
    Copy
  • 인라인 뷰는 일반적으로 :samp:`{left_hand_table_expression}`에서 하나 이상의 열을 참조하지만, 반드시 그렇게 할 필요는 없습니다.

  • INNER JOIN 구문이 쉼표나 INNER JOIN이라는 키워드를 사용할 수 있는 것처럼 래터럴 조인도 쉼표나 INNER JOIN이라는 키워드를 사용할 수 있습니다. 예:

    FROM departments AS d INNER JOIN LATERAL (...)
    
    Copy
  • 다음에서 ON, USING 또는 NATURAL JOIN 절을 지정할 수 없습니다.

    • 측면 테이블 함수(SQL UDTF 제외)

    • 테이블 함수에 대한 외부 측면 조인(SQL UDTF 제외)

    자세한 내용은 :ref:`JOIN 항목의 사용법 노트 <label-join_usage_notes>`를 참조하세요.

참고 항목: 예: FLATTEN 테이블 함수와 함께 래터럴 조인 사용FLATTEN을 사용하여 WHERE 절에서 결과 필터링하기.

다음 예제에서는 이러한 테이블을 사용합니다.

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

다음 쿼리는 하위 쿼리가 있는 측면 조인입니다.

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

다음 SQL 문은 동등하며 동일한 출력을 생성합니다. FROM 절의 쉼표 대신 INNER JOIN 키워드를 사용합니다.

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

중첩 데이터에 대한 LATERAL FLATTEN 연결

LATERAL은 여러 FLATTEN 호출을 연결하여 중첩된 데이터 구조에 액세스하는 경우에 필요합니다. 다음 예제에서 두 번째 FLATTEN은 첫 번째 FLATTEN의 출력을 참조해야 하며, 이는 LATERAL을 통해서만 가능합니다.

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

다음 쿼리는 두 개의 LATERAL FLATTEN 호출을 사용합니다. 첫 번째 호출은 contact 배열을 평면화하고 두 번째 호출은 각 연락처 내의 ``business``를 평면화합니다. 두 번째 FLATTEN 호출은 첫 번째 FLATTEN 호출의 출력에서 ​​나온 ``f.value``를 참조합니다.

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

두 번째 FLATTEN 호출은 첫 번째 FLATTEN 호출의 출력에 따라 달라지므로 이 쿼리는 LATERAL 없이 작성할 수 없습니다.

LATERAL 및 다른 접근 방식

다음 테이블에는 다른 접근 방식과 비교하여 LATERAL을 사용해야 하는 경우가 요약되어 있습니다.

사용 사례

권장 사항

단일 수준 배열 평면화

LATERAL이 없는 ``TABLE(FLATTEN(…))``은 동일하게 작동합니다. LATERAL은 선택 사항입니다.

중첩 배열(배열 내의 배열) 평면화

FLATTEN 호출을 연결하려면 LATERAL이 필요합니다.

현재 행을 기준으로 다른 테이블의 행 필터링

SELECT 목록 또는 LATERAL의 상관 하위 쿼리가 작동합니다. LATERAL은 여러 행과 열을 반환할 수 있으며 SELECT의 상관 하위 쿼리는 이 작업을 수행할 수 없습니다.

행별 입력으로 테이블 함수 호출

LATERAL을 사용하면 테이블 함수가 각 행에 대해 다른 인자를 수신할 수 있습니다.