세트 연산자

설정 연산자는 여러 쿼리 블록의 중간 결과를 하나의 결과 세트로 결합합니다.

일반 구문

[ ( ] <query> [ ) ] { INTERSECT | { MINUS | EXCEPT } | UNION [ ALL ] } [ ( ] <query> [ ) ]
[ ORDER BY ... ]
[ LIMIT ... ]
Copy

일반적인 사용법 노트

  • 각 쿼리는 그 자체가 쿼리 연산자를 포함함으로써 쿼리 식을 몇 개라도 세트 연산자와 결합할 수 있습니다.

  • ORDER BYLIMIT / FETCH 절은 세트 연산자의 결과에 적용됩니다.

  • 이들 연산자를 사용할 때 다음 사항이 적용됩니다.

    • 각 쿼리가 같은 수의 열을 선택하는지 확인하십시오.

    • 각 열의 데이터 타입이 서로 다른 원본의 행 전체에서 일치하는지 확인하십시오. UNION 연산자를 사용하여 일치하지 않는 데이터 타입을 형 변환합니다 섹션의 예제 중 하나는 데이터 타입이 일치하지 않을 때 발생할 수 있는 문제와 해결 방법을 보여줍니다.

    • 일반적으로, 열의 데이터 타입뿐 아니라 “의미”도 일치해야 합니다. 다음과 같은 방법은 원하는 결과를 얻지 못합니다.

      SELECT LastName, FirstName FROM employees
      UNION ALL
      SELECT FirstName, LastName FROM contractors;
      
      Copy

      예컨대, 별표를 사용해 테이블의 모든 열을 지정할 때 오류가 발생할 위험이 증가합니다.

      SELECT * FROM table1
      UNION ALL
      SELECT * FROM table2;
      
      Copy

      테이블의 열 수가 같지만 열의 순서가 같지 않은 경우 쿼리 결과가 올바르지 않을 수 있습니다.

    • 출력 열의 이름은 첫 번째 쿼리의 열 이름을 기반으로 합니다. 예를 들어, 다음 쿼리를 생각해 보십시오.

      SELECT LastName, FirstName FROM employees
      UNION ALL
      SELECT FirstName, LastName FROM contractors;
      
      Copy

      이 쿼리는 다음과 같은 쿼리처럼 동작합니다.

      SELECT LastName, FirstName FROM employees
      UNION ALL
      SELECT FirstName AS LastName, LastName AS FirstName FROM contractors;
      
      Copy
  • 세트 연산자의 우선 순위는 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');
Copy

INTERSECT

한 쿼리의 결과 세트에서 중복 제거와 함께 다른 쿼리의 결과 세트에도 나타나는 행을 반환합니다.

구문

SELECT ...
INTERSECT
SELECT ...
Copy

INTERSECT 연산자 예제

샘플 테이블 을 쿼리하여 영업소와 고객이 모두 있는 우편번호를 찾습니다.

SELECT zip FROM sales_office_zip_example
INTERSECT
SELECT zip FROM customer_zip_example;
Copy
+-------+
| ZIP   |
|-------|
| 94061 |
| 98005 |
+-------+

MINUS , EXCEPT

첫 번째 쿼리에서 반환한 행 중 두 번째 쿼리에서도 반환되지 않은 행을 반환합니다.

MINUS 및 EXCEPT 키워드는 같은 의미를 가지고 있고 서로 바꾸어 사용할 수 있습니다.

구문

SELECT ...
MINUS
SELECT ...

SELECT ...
EXCEPT
SELECT ...
Copy

MINUS 연산자 예제

샘플 테이블 을 쿼리하여 sales_office_zip_example 테이블에 없는 우편번호를 customer_zip_example 테이블에서 찾습니다.

SELECT zip FROM sales_office_zip_example
MINUS
SELECT zip FROM customer_zip_example;
Copy
+-------+
| ZIP   |
|-------|
| 98116 |
| 94070 |
+-------+

샘플 테이블 을 쿼리하여 customer_zip_example 테이블에 없는 우편번호를 sales_office_zip_example 테이블에서 찾습니다.

SELECT zip FROM customer_zip_example
MINUS
SELECT zip FROM sales_office_zip_example;
Copy
+-------+
| ZIP   |
|-------|
| 98444 |
| 94066 |
+-------+

UNION [ ALL ]

두 쿼리의 결과 세트를 결합합니다.

  • UNION 은 중복 제거와 함께 결합합니다.

  • UNIONALL 은 중복 제거 없이 결합합니다.

기본값은 UNION (즉, 중복 제거)입니다.

구문

SELECT ...
UNION [ ALL ]
SELECT ...
Copy

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

서로 다른 데이터 타입(union_test1 의 VARCHAR 값 및 union_test2 의 INTEGER 값)을 사용하여 UNION 작업을 실행합니다.

SELECT v FROM union_test1
UNION
SELECT i FROM union_test2;
Copy

이 쿼리는 오류를 반환합니다.

100038 (22018): Numeric value 'Adams, Douglas' is not recognized

이제 명시적 캐스팅을 사용해 입력값을 호환 가능한 형식으로 변환합니다.

SELECT v::VARCHAR FROM union_test1
UNION
SELECT i::VARCHAR FROM union_test2;
Copy
+----------------+
| V::VARCHAR     |
|----------------|
| Adams, Douglas |
| 42             |
+----------------+