데이터 모델과 SQL

[데이터 모델과 SQL] 9. UNION 연산

영바이트 2023. 1. 10. 16:16

 

교집합(INTERSECT)과 여집합(EXCEPT)을 각각 INNER JOIN과 OUTER JOIN으로 구할 수 있다.

- 교집합: 교집합을 구하고자 하는 결과 셋들을 공통 키를 기준으로 INNER JOIN 하면 결과 셋들에 모두 포함되어 있는 행들, 즉 교집합을 구할 수 있다.

- 여집합: 여집합을 구하고자 하는 대상이 되는 결과 셋들을 OUTER JOIN하고 참조 셋에 데이터가 없는(IS NULL) 조건을 설정하면 '기준 셋 - 참조 셋'에 해당하는 결과 셋을 얻을 수 있다.

 

합집합(UNION) 연산은 일반적으로 JOIN 연산으로 대체하지 않고 그대로 사용되는 경우가 많다.
문법: <검색식 1> UNION [ALL] <검색식 2>


*ALL 키워드를 사용하면 중복된 결과들까지 모두 보여준다. DBMS(DateBase Management System)가 중복 결과 제거 작업을 하지 않아도 되므로 실행 속도 측면에서 유리하다.

 

UNION 연산의 특징은 결과 셋을 합친다는 것이다. 즉, 아래 조건을 만족하여 결과 셋이 합쳐질 수 있는 경우에만 UNION 연산을 사용할 수 있다.
ⓐ 결과 셋들의 컬럼 수가 같아야 한다.
ⓑ 결과 셋들의 컬럼의 데이터 형식이 같아야 한다.

 

예) 고객(customer)과 거래처(vendor)의 이름, 상세주소(address), 거주하는 도시(city), 거주하는 주(state), 그리고 우편번호(ZIP Code)로 이루어진 주소록을 얻고 싶다.

SELECT CONCAT(CustFirstName, ' ', CustLastName), CustStreetAddress, CustCity, CustState, CustZipCode FROM customers 
UNION ALL 
SELECT VendName, VendStreetAddress, VendCity, VendState, VendZipCode FROM vendors;

 

*UNION 연산 결과 출력되는 데이터들의 컬럼 이름은 DBMS에 따라 다르다. 일반적으로 첫 번째 검색식에 지정한 컬럼 이름이 사용된다.

 

● 가상테이블과 UNION 연산
테이블들을 JOIN 연산하여 얻은 가상 테이블에 UNION 연산을 적용하는 것도 가능하다.

 

예) 고객 명단과 주문한 자전거의 종류 그리고 자전거 생산자와 생산하는 자전거의 종류를 알고 싶다.

SELECT customers.CustomerID, CONCAT(customers.CustFirstName, ' ', customers.CustLastName), products.ProductName FROM 
(((customers LEFT OUTER JOIN orders ON customers.CustomerID=orders.CustomerID) 
LEFT OUTER JOIN order_details ON orders.OrderNumber=order_details.OrderNumber) 
LEFT OUTER JOIN products ON order_details.ProductNumber=products.ProductNumber) 
LEFT OUTER JOIN categories ON products.CategoryID=categories.CategoryID WHERE categories.CategoryDescription='Bikes'
UNION
SELECT vendors.VendorID, vendors.vendName, products.ProductName 
FROM ((vendors LEFT OUTER JOIN product_vendors ON vendors.VendorID=product_vendors.VendorID) 
LEFT OUTER JOIN products ON product_vendors.ProductNumber=products.ProductNumber) 
LEFT OUTER JOIN categories ON products.CategoryID=categories.CategoryID 
WHERE categories.CategoryDescription='Bikes';

 

사실 SELECT 구문의 결과가 (가상) 테이블이기 때문에 SELECT 구문으로 얻어진 가상 테이블들을 합치는 것이 안 될 이유는 없다. 단지 ⓐ 결과 셋들의 컬럼 수가 같아야 한다. ⓑ 결과 셋들의 컬럼의 데이터 형식이 같아야 한다. 이 두 조건을 만족하느냐 그렇지 않느냐 만이 문제가 될 뿐이다.

 

 

● UNION 결과 정렬하기
UNION 연산의 결과 셋을 정렬하기 위해서는 제일 마지막 검색식 뒤에 한 번만 ORDER BY 키워드를 사용한다.
예) <검색식 1> UNION <검색식 2> UNION <검색식 3> ... ORDER BY <표현식, 컬럼> [DESC/ASC]