세트 연산자¶
설정 연산자는 여러 쿼리 블록의 중간 결과를 하나의 결과 세트로 결합합니다.
일반 구문¶
[ ( ] <query> [ ) ] { INTERSECT | { MINUS | EXCEPT } | UNION [ ALL ] } [ ( ] <query> [ ) ]
[ ORDER BY ... ]
[ LIMIT ... ]
일반적인 사용법 노트¶
각 쿼리는 그 자체가 쿼리 연산자를 포함함으로써 쿼리 식을 몇 개라도 세트 연산자와 결합할 수 있습니다.
ORDER BY 및 LIMIT / FETCH 절은 세트 연산자의 결과에 적용됩니다.
이들 연산자를 사용할 때 다음 사항이 적용됩니다.
각 쿼리가 같은 수의 열을 선택하는지 확인하십시오.
각 열의 데이터 타입이 서로 다른 원본의 행 전체에서 일치하는지 확인하십시오. UNION 연산자를 사용하여 일치하지 않는 데이터 타입을 형 변환합니다 섹션의 예제 중 하나는 데이터 타입이 일치하지 않을 때 발생할 수 있는 문제와 해결 방법을 보여줍니다.
일반적으로, 열의 데이터 타입뿐 아니라 “의미”도 일치해야 합니다. 다음과 같은 방법은 원하는 결과를 얻지 못합니다.
SELECT LastName, FirstName FROM employees UNION ALL SELECT FirstName, LastName FROM contractors;
예컨대, 별표를 사용해 테이블의 모든 열을 지정할 때 오류가 발생할 위험이 증가합니다.
SELECT * FROM table1 UNION ALL SELECT * FROM table2;
테이블의 열 수가 같지만 열의 순서가 같지 않은 경우 쿼리 결과가 올바르지 않을 수 있습니다.
출력 열의 이름은 첫 번째 쿼리의 열 이름을 기반으로 합니다. 예를 들어, 다음 쿼리를 생각해 보십시오.
SELECT LastName, FirstName FROM employees UNION ALL SELECT FirstName, LastName FROM contractors;
이 쿼리는 다음과 같은 쿼리처럼 동작합니다.
SELECT LastName, FirstName FROM employees UNION ALL SELECT FirstName AS LastName, LastName AS FirstName FROM contractors;
세트 연산자의 우선 순위는 ANSI 및 ISO SQL 표준과 일치합니다.
UNION [ALL] 및 MINUS (EXCEPT) 연산자는 우선 순위가 같습니다.
INTERSECT 연산자는 UNION [ALL] 및 MINUS (EXCEPT)보다 우선 순위가 높습니다.
우선 순위가 같은 연산자는 왼쪽에서 오른쪽으로 처리됩니다.
괄호를 사용하여 식을 다른 순서로 평가하도록 적용할 수 있습니다.
모든 데이터베이스 벤더가 set 연산자의 우선 순위에 대해 ANSI/ISO 표준을 따르는 것은 아닙니다. 특히 다른 벤더의 코드를 Snowflake로 포팅하거나 Snowflake뿐 아니라 다른 데이터베이스에서도 실행할 수 있는 코드를 작성하는 경우 괄호를 사용하여 평가 순서를 지정하는 것이 좋습니다.
예제용 샘플 테이블¶
이 항목의 예제에서는 다음 샘플 테이블을 사용합니다. 두 테이블 모두 우편 번호 열이 있습니다. 한 테이블에는 각 영업소의 우편 번호가 기록되고 다른 테이블에는 각 고객의 우편 번호가 기록됩니다.
CREATE OR REPLACE TABLE sales_office_zip_example(
office_name VARCHAR,
zip VARCHAR);
INSERT INTO sales_office_zip_example VALUES ('sales1', '94061');
INSERT INTO sales_office_zip_example VALUES ('sales2', '94070');
INSERT INTO sales_office_zip_example VALUES ('sales3', '98116');
INSERT INTO sales_office_zip_example VALUES ('sales4', '98005');
CREATE OR REPLACE TABLE customer_zip_example(
customer VARCHAR,
zip VARCHAR);
INSERT INTO customer_zip_example VALUES ('customer1', '94066');
INSERT INTO customer_zip_example VALUES ('customer2', '94061');
INSERT INTO customer_zip_example VALUES ('customer3', '98444');
INSERT INTO customer_zip_example VALUES ('customer4', '98005');
INTERSECT¶
한 쿼리의 결과 세트에서 중복 제거와 함께 다른 쿼리의 결과 세트에도 나타나는 행을 반환합니다.
구문¶
SELECT ...
INTERSECT
SELECT ...
INTERSECT 연산자 예제¶
샘플 테이블 을 쿼리하여 영업소와 고객이 모두 있는 우편번호를 찾습니다.
SELECT zip FROM sales_office_zip_example
INTERSECT
SELECT zip FROM customer_zip_example;
+-------+
| ZIP |
|-------|
| 94061 |
| 98005 |
+-------+
MINUS , EXCEPT¶
첫 번째 쿼리에서 반환한 행 중 두 번째 쿼리에서도 반환되지 않은 행을 반환합니다.
MINUS 및 EXCEPT 키워드는 같은 의미를 가지고 있고 서로 바꾸어 사용할 수 있습니다.
구문¶
SELECT ...
MINUS
SELECT ...
SELECT ...
EXCEPT
SELECT ...
MINUS 연산자 예제¶
샘플 테이블 을 쿼리하여 sales_office_zip_example
테이블에 없는 우편번호를 customer_zip_example
테이블에서 찾습니다.
SELECT zip FROM sales_office_zip_example
MINUS
SELECT zip FROM customer_zip_example;
+-------+
| ZIP |
|-------|
| 98116 |
| 94070 |
+-------+
샘플 테이블 을 쿼리하여 customer_zip_example
테이블에 없는 우편번호를 sales_office_zip_example
테이블에서 찾습니다.
SELECT zip FROM customer_zip_example
MINUS
SELECT zip FROM sales_office_zip_example;
+-------+
| ZIP |
|-------|
| 98444 |
| 94066 |
+-------+
UNION [ ALL ]¶
두 쿼리의 결과 세트를 결합합니다.
UNION 은 중복 제거와 함께 결합합니다.
UNIONALL 은 중복 제거 없이 결합합니다.
기본값은 UNION (즉, 중복 제거)입니다.
구문¶
SELECT ...
UNION [ ALL ]
SELECT ...
UNION 연산자 예제¶
다음 예제에서는 UNION 연산자를 사용합니다.
UNION 연산자를 사용하여 두 쿼리 결과를 결합합니다¶
UNION 연산자를 사용하여 샘플 테이블 에서 두 쿼리의 결과 세트를 결합합니다.
SELECT office_name office_or_customer, zip FROM sales_office_zip_example
UNION
SELECT customer, zip FROM customer_zip_example
ORDER BY zip;
+--------------------+-------+
| OFFICE_OR_CUSTOMER | ZIP |
|--------------------+-------|
| sales1 | 94061 |
| customer2 | 94061 |
| customer1 | 94066 |
| sales2 | 94070 |
| sales4 | 98005 |
| customer4 | 98005 |
| sales3 | 98116 |
| customer3 | 98444 |
+--------------------+-------+
UNION 연산자를 사용하여 일치하지 않는 데이터 타입을 형 변환합니다¶
이 예제에서는 데이터 타입이 일치하지 않을 때 UNION 연산자를 사용할 때 발생할 수 있는 문제를 보여주고 해결 방법을 제공합니다.
먼저 테이블 만들기와 데이터 삽입부터 시작합니다.
CREATE OR REPLACE TABLE union_test1 (v VARCHAR);
CREATE OR REPLACE TABLE union_test2 (i INTEGER);
INSERT INTO union_test1 (v) VALUES ('Adams, Douglas');
INSERT INTO union_test2 (i) VALUES (42);
서로 다른 데이터 타입(union_test1
의 VARCHAR 값 및 union_test2
의 INTEGER 값)을 사용하여 UNION 작업을 실행합니다.
SELECT v FROM union_test1
UNION
SELECT i FROM union_test2;
이 쿼리는 오류를 반환합니다.
100038 (22018): Numeric value 'Adams, Douglas' is not recognized
이제 명시적 캐스팅을 사용해 입력값을 호환 가능한 형식으로 변환합니다.
SELECT v::VARCHAR FROM union_test1
UNION
SELECT i::VARCHAR FROM union_test2;
+----------------+
| V::VARCHAR |
|----------------|
| Adams, Douglas |
| 42 |
+----------------+