- 카테고리:
JOIN¶
JOIN
작업은 두 테이블(또는 뷰나 테이블 함수와 같은 다른 테이블 유사 소스)의 행을 결합하여, 쿼리에 사용할 수 있는 결합된 새 행을 만듭니다. 조인에 대한 개념 설명은 조인 관련 작업하기 을 참조하십시오.
이 항목에서는 FROM 절에서 JOIN
구문을 사용하는 방법에 대해 설명합니다. JOIN
하위 절은 한 테이블의 행을 다른 테이블의 해당 행과 관련시키는 방법을 (명시적 또는 암시적으로) 지정합니다. 값이 서로 밀접하게 후행하거나 선행하거나 정확히 일치하는 경우 타임스탬프 열의 시계열 데이터를 조인하는 데 사용되는 ASOF JOIN 도 참조하십시오.
테이블을 조인하는 데 권장되는 방법은 FROM
절의 ON
하위 절과 함께 JOIN
을 사용하는 것이지만, 테이블을 조인하는 다른 방법은 WHERE
절을 사용하는 것입니다. 자세한 내용은 WHERE 절에 대한 설명서를 참조하십시오.
구문¶
다음 중 하나를 사용하십시오.
SELECT ...
FROM <object_ref1> [
{
INNER
| { LEFT | RIGHT | FULL } [ OUTER ]
}
]
JOIN <object_ref2>
[ ON <condition> ]
[ ... ]
SELECT *
FROM <object_ref1> [
{
INNER
| { LEFT | RIGHT | FULL } [ OUTER ]
}
]
JOIN <object_ref2>
[ USING( <column_list> ) ]
[ ... ]
SELECT ...
FROM <object_ref1> [
{
| NATURAL [ { LEFT | RIGHT | FULL } [ OUTER ] ]
| CROSS
}
]
JOIN <object_ref2>
[ ... ]
object_ref1
및object_ref2
각 오브젝트 참조는 테이블 또는 테이블과 유사한 데이터 소스입니다.
JOIN
JOIN
키워드를 사용하여, 테이블을 조인해야 함을 지정하십시오.JOIN
을 다른 조인 관련 키워드(예:INNER
또는OUTER
)와 결합하여 조인 유형을 지정하십시오.조인의 의미 체계는 다음과 같습니다(간결함을 위해 이 항목에서는
o1
및o2
에 대해 각각object_ref1
및object_ref2
를 사용함).조인 유형
의미 체계
o1 INNER JOIN o2
o1
의 각 행의 경우,ON condition
하위 절에 따라 일치하는o2
의 각 행에 대해 행이 생성됩니다. (쉼표를 사용하여 내부 조인을 지정할 수도 있습니다. 예를 들어, 아래의 예 섹션을 참조하십시오.)ON
절 없이INNER JOIN
을 사용하는 경우(또는WHERE
절 없이 쉼표를 사용하는 경우), 결과는CROSS JOIN
을 사용하는 것과 동일합니다. 즉, 데카르트 곱(o1
의 모든 행은o2
의 모든 행과 쌍을 이룸)입니다.o1 LEFT OUTER JOIN o2
내부 조인의 결과는
o1
에 일치 항목이 없는o2
의 각 행에 대한 행으로 증가됩니다.o2
를 참조하는 결과 열에 null이 포함되어 있습니다.o1 RIGHT OUTER JOIN o2
내부 조인의 결과는
o2
에 일치 항목이 없는o1
의 각 행에 대한 행으로 증가됩니다.o1
를 참조하는 결과 열에 null이 포함되어 있습니다.o1 FULL OUTER JOIN o2
조인된 모든 행, 그리고 일치하지 않는 왼쪽 행(오른쪽이 null로 확장됨)에 대한 행 하나, 그리고 일치하지 않는 오른쪽 행(왼쪽이 null로 확장됨)에 대한 행 하나를 반환합니다.
o1 CROSS JOIN o2
o1
및o2
의 가능한 모든 행 조합(즉, 데카르트 곱)의 경우, 조인된 테이블에는o1
의 모든 열에 이어o2
의 모든 열로 구성된 행이 포함됩니다.CROSS JOIN
은ON condition
절과 결합할 수 없습니다. 그러나WHERE
절을 사용하여 결과를 필터링할 수 있습니다.o1 NATURAL JOIN o2
NATURAL JOIN
은 공통 열이 출력에 한 번만 포함된다는 점을 제외하고는, 두 테이블의 공통 열에 대한 명시적JOIN
과 동일합니다. (자연 조인은 이름이 같되 테이블이 다른 열에 해당 데이터가 포함되어 있다고 가정합니다.) 몇 가지 예는 아래의 예 섹션을 참조하십시오.NATURAL JOIN
은OUTER JOIN
과 결합할 수 있습니다.JOIN
조건이 이미 내포되어 있으므로NATURAL JOIN
을ON condition
절과 결합할 수 없습니다. 그러나WHERE
절을 사용하여 결과를 필터링할 수 있습니다.참고 항목:
기본값:
INNER JOIN
INNER
또는OUTER
를 지정하지 않고JOIN
단어를 사용하는 경우,JOIN
은 내부 조인입니다.ON condition
일치하는 것으로 간주되는
JOIN
의 두 측면에서 행을 정의하는 부울 식입니다. 예를 들면 다음과 같습니다.ON object_ref2.id_number = object_ref1.id_number
조건은 WHERE 절 문서에서 더 자세히 설명합니다.
ON
절은CROSS JOIN
에는 금지됩니다.ON
절은NATURAL JOIN
에 필요하지 않으며 금지됩니다. 조인 열은 내포됩니다.다른 조인의 경우,
ON
절은 선택 사항입니다. 그러나ON
절을 생략하면 데카르트 곱이 생성됩니다(object_ref1
의 모든 행은object_ref2
의 모든 행과 쌍을 이룸). 데카르트 곱은 매우 많은 양의 출력을 생성할 수 있으며, 그중 거의 모두는 실제로는 관련되지 않은 행 쌍으로 구성됩니다. 이는 많은 리소스를 사용하며, 사용자 오류인 경우가 많습니다.USING( <column_list> )
조인되는 두 테이블 사이의 공통 열 목록입니다. 이러한 열은 조인 열로 사용됩니다. 열은 조인되는 각 테이블에서 동일한 이름과 의미를 가져야 합니다.
예를 들어, SQL 문에 다음이 포함되어 있다고 가정합니다.
... o1 JOIN o2 USING (key_column)
간단한 경우에 이는 다음과 같습니다.
... o1 JOIN o2 ON o2.key_column = o1.key_column
표준 JOIN 구문에서 프로젝션 목록(SELECT 키워드 뒤에 있는 열과 기타 식의 목록)은 “*”입니다. 이로 인해 쿼리가
key_column
을 정확히 한 번 반환합니다. 열은 다음 순서로 반환됩니다.USING 절의 열(지정된 순서대로 반환).
USING 절에 지정되지 않은 왼쪽 테이블 열.
USING 절에 지정되지 않은 오른쪽 테이블 열.
표준 및 비표준 사용법의 예는 아래 예를 참조하십시오.
사용법 노트¶
SQL UDTF 이외의 테이블 함수에는 다음 제한 사항이 적용됩니다.
측면 테이블 함수(SQL UDTF 제외)에는 ON, USING 또는 NATURAL JOIN 절을 지정할 수 없습니다.
예를 들어 다음 구문은 허용되지 않습니다.
SELECT ... FROM my_table JOIN TABLE(FLATTEN(input=>[col_a])) ON ... ;
SELECT ... FROM my_table INNER JOIN TABLE(FLATTEN(input=>[col_a])) ON ... ;
SELECT ... FROM my_table JOIN TABLE(my_js_udtf(col_a)) ON ... ;
SELECT ... FROM my_table INNER JOIN TABLE(my_js_udtf(col_a)) ON ... ;
테이블 함수(SQL UDTF 제외)에 대한 외부 측면 조인에는 ON, USING 또는 NATURAL JOIN 절을 지정할 수 없습니다.
예를 들어 다음 구문은 허용되지 않습니다.
SELECT ... FROM my_table LEFT JOIN TABLE(FLATTEN(input=>[a])) ON ... ;
SELECT ... FROM my_table FULL JOIN TABLE(FLATTEN(input=>[a])) ON ... ;
SELECT ... FROM my_table LEFT JOIN TABLE(my_js_udtf(a)) ON ... ;
SELECT ... FROM my_table FULL JOIN TABLE(my_js_udtf(a)) ON ... ;
위에서 이 구문을 사용하면 다음 오류가 발생합니다.
000002 (0A000): Unsupported feature 'lateral table function called with OUTER JOIN syntax or a join predicate (ON clause)'
JOIN 키워드가 아닌 쉼표를 사용하는 경우에는 이러한 제한 사항이 적용되지 않습니다.
SELECT ... FROM my_table, TABLE(FLATTEN(input=>[col_a])) ON ... ;
예¶
많은 JOIN
예에서는 t1
및 t2
라는 두 개의 테이블을 사용합니다. 이 테이블과 해당 데이터는 아래와 같이 만들어집니다.
CREATE TABLE t1 (col1 INTEGER); CREATE TABLE t2 (col1 INTEGER);INSERT INTO t1 (col1) VALUES (2), (3), (4); INSERT INTO t2 (col1) VALUES (1), (2), (2), (3);
내부 조인:
SELECT t1.col1, t2.col1 FROM t1 INNER JOIN t2 ON t2.col1 = t1.col1 ORDER BY 1,2; +------+------+ | COL1 | COL1 | |------+------| | 2 | 2 | | 2 | 2 | | 3 | 3 | +------+------+
이는 왼쪽 외부 조인을 보여줍니다. 테이블 t2에 일치하는 행이 없는 테이블 t1의 행에 대한 NULL 값에 유의하십시오.
SELECT t1.col1, t2.col1 FROM t1 LEFT OUTER JOIN t2 ON t2.col1 = t1.col1 ORDER BY 1,2; +------+------+ | COL1 | COL1 | |------+------| | 2 | 2 | | 2 | 2 | | 3 | 3 | | 4 | NULL | +------+------+
이는 오른쪽 외부 조인을 보여줍니다. 테이블 t2에 일치하는 행이 없는 테이블 t1의 행에 대한 NULL 값에 유의하십시오.
SELECT t1.col1, t2.col1 FROM t1 RIGHT OUTER JOIN t2 ON t2.col1 = t1.col1 ORDER BY 1,2; +------+------+ | COL1 | COL1 | |------+------| | 2 | 2 | | 2 | 2 | | 3 | 3 | | NULL | 1 | +------+------+
이는 전체 외부 조인을 보여줍니다. 각 테이블에는 다른 테이블에서 일치하는 행이 없는 행이 있기 때문에 출력에는 다음과 같이 NULL 값이 있는 두 개의 행이 포함된다는 것에 유의하십시오.
SELECT t1.col1, t2.col1 FROM t1 FULL OUTER JOIN t2 ON t2.col1 = t1.col1 ORDER BY 1,2; +------+------+ | COL1 | COL1 | |------+------| | 2 | 2 | | 2 | 2 | | 3 | 3 | | 4 | NULL | | NULL | 1 | +------+------+
다음은 데카르트 곱을 생성하는 크로스 조인의 예입니다. 크로스 조인에는 ON 절이 없음에 유의하십시오.
SELECT t1.col1, t2.col1 FROM t1 CROSS JOIN t2 ORDER BY 1, 2; +------+------+ | COL1 | COL1 | |------+------| | 2 | 1 | | 2 | 2 | | 2 | 2 | | 2 | 3 | | 3 | 1 | | 3 | 2 | | 3 | 2 | | 3 | 3 | | 4 | 1 | | 4 | 2 | | 4 | 2 | | 4 | 3 | +------+------+
크로스 조인은 아래 예와 같이 WHERE
절로 필터링할 수 있습니다.
SELECT t1.col1, t2.col1 FROM t1 CROSS JOIN t2 WHERE t2.col1 = t1.col1 ORDER BY 1, 2; +------+------+ | COL1 | COL1 | |------+------| | 2 | 2 | | 2 | 2 | | 3 | 3 | +------+------+
이는 자연 조인의 예입니다. 이렇게 할 경우, 출력에 조인 열의 두 번째 복사본이 포함되지 않는다는 점을 제외하고는, 해당 내부 조인과 동일한 출력이 다음과 같이 생성됩니다.
CREATE OR REPLACE TABLE d1 ( id number, name string ); +--------------------------------+ | status | |--------------------------------| | Table D1 successfully created. | +--------------------------------+ INSERT INTO d1 (id, name) VALUES (1,'a'), (2,'b'), (4,'c'); +-------------------------+ | number of rows inserted | |-------------------------| | 3 | +-------------------------+ CREATE OR REPLACE TABLE d2 ( id number, value string ); +--------------------------------+ | status | |--------------------------------| | Table D2 successfully created. | +--------------------------------+ INSERT INTO d2 (id, value) VALUES (1,'xx'), (2,'yy'), (5,'zz'); +-------------------------+ | number of rows inserted | |-------------------------| | 3 | +-------------------------+ SELECT * FROM d1 NATURAL INNER JOIN d2 ORDER BY id; +----+------+-------+ | ID | NAME | VALUE | |----+------+-------| | 1 | a | xx | | 2 | b | yy | +----+------+-------+
자연 조인은 외부 조인과 결합될 수 있습니다. 예를 들면 다음과 같습니다.
SELECT * FROM d1 NATURAL FULL OUTER JOIN d2 ORDER BY ID; +----+------+-------+ | ID | NAME | VALUE | |----+------+-------| | 1 | a | xx | | 2 | b | yy | | 4 | c | NULL | | 5 | NULL | zz | +----+------+-------+
조인은 FROM
절에서 결합될 수 있습니다. 다음 코드는 세 번째 테이블을 만든 다음 FROM 절에서 두 개의 JOIN을 연결합니다.
CREATE TABLE t3 (col1 INTEGER); INSERT INTO t3 (col1) VALUES (2), (6);SELECT t1.*, t2.*, t3.* FROM t1 LEFT OUTER JOIN t2 ON (t1.col1 = t2.col1) RIGHT OUTER JOIN t3 ON (t3.col1 = t2.col1) ORDER BY t1.col1; +------+------+------+ | COL1 | COL1 | COL1 | |------+------+------| | 2 | 2 | 2 | | 2 | 2 | 2 | | NULL | NULL | 6 | +------+------+------+
이러한 쿼리에서 결과는 왼쪽에서 오른쪽으로 발생하는 조인을 기반으로 결정됩니다(단, 다른 조인 순서가 동일 결과를 생성하는 경우, 옵티마이저가 조인을 재정렬할 수 있음). 오른쪽 외부 조인이 왼쪽 외부 조인보다 먼저 발생해야 하는 경우, 쿼리는 다음과 같이 작성할 수 있습니다.
SELECT t1.*, t2.*, t3.* FROM t1 LEFT OUTER JOIN (t2 RIGHT OUTER JOIN t3 ON (t3.col1 = t2.col1)) ON (t1.col1 = t2.col1) ORDER BY t1.col1; +------+------+------+ | COL1 | COL1 | COL1 | |------+------+------| | 2 | 2 | 2 | | 2 | 2 | 2 | | 3 | NULL | NULL | | 4 | NULL | NULL | +------+------+------+
아래의 두 가지 예는 USING
절의 표준(ISO 9075) 및 비표준 사용법을 보여줍니다. 둘 다 Snowflake에서 지원됩니다.
이 첫 번째 예는 표준 사용법을 보여줍니다. 특히 프로젝션 목록에는 정확히 “*”가 포함됩니다. 예시 쿼리가 두 개의 테이블을 조인하고, 각 테이블에 하나의 열이 있고, 쿼리가 모든 열을 요청하더라도 출력에는 두 개의 열이 아니라 하나의 열이 포함됩니다.
WITH
l AS (
SELECT 'a' AS userid
),
r AS (
SELECT 'b' AS userid
)
SELECT *
FROM l LEFT JOIN r USING(userid)
;
+--------+
| USERID |
|--------|
| a |
+--------+
다음 예에서는 비표준 사용법을 보여줍니다. 프로젝션 목록에는 “*”가 아닌 다른 항목이 포함됩니다. 출력에는 두 개의 열이 포함되며 두 번째 열에는 두 번째 테이블의 값 또는 NULL이 포함됩니다.
WITH
l AS (
SELECT 'a' AS userid
),
r AS (
SELECT 'b' AS userid
)
SELECT l.userid as UI_L,
r.userid as UI_R
FROM l LEFT JOIN r USING(userid)
;
+------+------+
| UI_L | UI_R |
|------+------|
| a | NULL |
+------+------+