Search
moon
sun

17.집합 연산자

•
집합 연산자로 두 조회 결과를 위아래(행)로 합칠 수 있다.
•
UNION 과 UNION ALL 의 차이(중복 제거·정렬·성능)를 설명할 수 있다.
•
INTERSECT(교집합)와 MINUS(차집합)를 사용할 수 있다.
•
집합 연산에서 ORDER BY 의 위치 규칙을 안다.

1. 집합 연산자란

1) 두 SELECT 결과를 세로로 합친다

네 가지 집합 연산자
의미
집합 기호
UNION
합집합 (중복 제거)
A ∪ B
UNION ALL
합집합 (중복 유지)
A + B
INTERSECT
교집합 (공통)
A ∩ B
MINUS
차집합 (A에만)
A − B

2. 사용 규칙 ⭐⭐⭐

두 SELECT의 ① 컬럼 개수, ② 순서, ③ 데이터 타입이 일치해야 한다.
-- ============================================================ -- 【시험용 예제】 규칙을 어기면 오류 ★★ -- ============================================================ -- ❌ 컬럼 개수가 다름 SELECT ENAME, SAL FROM EMP WHERE DEPTNO = 10 UNION SELECT ENAME FROM EMP WHERE DEPTNO = 20; -- 컬럼 1개! -- ORA-01789: query block has incorrect number of result columns -- ❌ 데이터 타입이 다름 (2번째 컬럼: 숫자 vs 문자) SELECT ENAME, SAL FROM EMP WHERE DEPTNO = 10 UNION SELECT ENAME, JOB FROM EMP WHERE DEPTNO = 20; -- SAL(숫자) vs JOB(문자) -- ORA-01790: expression must have same datatype as corresponding expression -- ✅ 개수·순서·타입이 모두 일치 SELECT ENAME, SAL FROM EMP WHERE DEPTNO = 10 UNION SELECT ENAME, SAL FROM EMP WHERE DEPTNO = 20; -- 정상 ✅
SQL
복사

1) 컬럼명은 첫 번째 SELECT 기준 ⭐

-- 결과의 컬럼명(헤더)은 '첫 번째' SELECT 것을 따른다 SELECT ENAME AS 사원명, SAL FROM EMP WHERE DEPTNO = 10 UNION SELECT ENAME AS 이름, SAL FROM EMP WHERE DEPTNO = 20; -- 사원명 SAL ← 헤더는 첫 SELECT의 '사원명' (두 번째 '이름' 은 무시됨) -- ------ ----- -- ...
SQL
복사
⭐ 두 번째 이후 SELECT의 컬럼명·별칭은 무시됩니다. 헤더는 항상 첫 SELECT 기준입니다.

3. UNION vs UNION ALL ⭐⭐⭐

🔥 이 단원 최다 출제입니다. 결과와 성능 두 관점으로 알아두세요.

1) 핵심 차이

UNION
UNION ALL
중복 행
제거
그대로 유지
정렬
자동 정렬됨
정렬 안 함
성능
느림 (중복 제거·정렬 비용)
빠름
권장
중복 제거가 필요할 때
중복이 없거나 상관없을 때
-- ============================================================ -- 【시험용 예제】 UNION 과 UNION ALL 의 결과 건수 차이 ★★★ -- 일부러 겹치는 조건으로 두 집합을 만든다 -- 집합A: 급여 2000 이상 집합B: 20번 부서 -- → 20번 부서이면서 급여 2000 이상인 사원(JONES,SCOTT,FORD)은 양쪽에 다 있다 -- ============================================================ -- UNION : 중복 제거 → 겹치는 사원은 한 번만 SELECT ENAME FROM EMP WHERE SAL >= 2000 UNION SELECT ENAME FROM EMP WHERE DEPTNO = 20; -- → 급여 2000이상(6명) + 20번부서(5명) 중 겹치는 3명 제거 = 8건 -- JONES, SCOTT, FORD 는 양쪽 조건을 다 만족하지만 '한 번만' 나온다 -- UNION ALL : 중복 유지 → 겹치는 사원은 두 번 SELECT ENAME FROM EMP WHERE SAL >= 2000 UNION ALL SELECT ENAME FROM EMP WHERE DEPTNO = 20; -- → 6 + 5 = 11건 (JONES, SCOTT, FORD 가 각각 두 번씩 나옴) -- -- ⭐ 결과 건수가 다르다: UNION 8건 vs UNION ALL 11건 -- ⭐ 성능 관점: 중복이 없다는 것이 확실하면 UNION ALL 이 빠르다. -- UNION 은 중복 제거를 위해 내부적으로 정렬(SORT)을 하기 때문이다.
SQL
복사

2) UNION 은 결과가 정렬되어 나온다

SELECT ENAME FROM EMP WHERE DEPTNO = 10 UNION SELECT ENAME FROM EMP WHERE DEPTNO = 20; -- ENAME -- ------ -- ADAMS ← ORDER BY 를 안 썼는데도 -- CLARK 중복 제거 과정에서 -- FORD 자동으로 정렬되어 나온다 -- JONES -- KING -- ... -- ⚠️ 단, 이 정렬은 '보장' 되는 게 아니므로 정렬이 필요하면 ORDER BY 를 명시해야 한다.
SQL
복사

4. INTERSECT — 교집합 ⭐

-- ============================================================ -- 【이해용 예제】 급여 2000 이상 '이면서' 20번 부서인 사원 ★ -- ============================================================ SELECT ENAME FROM EMP WHERE SAL >= 2000 INTERSECT SELECT ENAME FROM EMP WHERE DEPTNO = 20; -- ENAME -- ------ -- FORD -- JONES -- SCOTT → 3건 (양쪽 집합에 모두 있는 사원) -- -- ⭐ INTERSECT = 두 집합의 '공통' 부분만. 이것도 중복을 제거하고 정렬한다. -- 같은 결과를 AND 조건으로도 낼 수 있다: -- WHERE SAL >= 2000 AND DEPTNO = 20
SQL
복사

5. MINUS — 차집합 ⭐⭐

1) A에는 있고 B에는 없는 것

-- ============================================================ -- 【이해용 예제】 급여 2000 이상이지만 20번 부서는 '아닌' 사원 ★ -- ============================================================ SELECT ENAME FROM EMP WHERE SAL >= 2000 MINUS SELECT ENAME FROM EMP WHERE DEPTNO = 20; -- ENAME -- ------ -- BLAKE ← 30번, 급여 2850 -- CLARK ← 10번, 급여 2450 -- KING ← 10번, 급여 5000 -- → 3건 (급여 2000이상 6명 - 20번부서 3명 = 3명) -- -- ⭐ 급여 2000이상 {JONES,BLAKE,SCOTT,KING,FORD,CLARK} 에서 -- 20번 부서 {JONES,SCOTT,FORD} 를 빼면 → {BLAKE,KING,CLARK}
SQL
복사

2) ⚠️ 순서가 결과를 바꾼다 ⭐⭐

-- ============================================================ -- 【시험용 예제】 A MINUS B ≠ B MINUS A ★★ -- "10번 부서엔 있고 30번엔 없는 직무" vs 그 반대 -- ============================================================ -- 10번 - 30번 : 10번에만 있는 직무 SELECT JOB FROM EMP WHERE DEPTNO = 10 MINUS SELECT JOB FROM EMP WHERE DEPTNO = 30; -- JOB -- --------- -- PRESIDENT ← 10번엔 사장이 있고 30번엔 없다 → 1건 -- (MANAGER, CLERK 는 양쪽에 다 있어서 제외) -- 30번 - 10번 : 30번에만 있는 직무 (순서를 바꿈) SELECT JOB FROM EMP WHERE DEPTNO = 30 MINUS SELECT JOB FROM EMP WHERE DEPTNO = 10; -- JOB -- --------- -- SALESMAN ← 30번엔 영업사원이 있고 10번엔 없다 → 1건 -- -- ⭐ 순서에 따라 결과가 완전히 다르다. MINUS 는 '방향' 이 중요하다. -- ⚠️ SQL Server 등 다른 DBMS 는 MINUS 대신 EXCEPT 를 쓴다 (기능은 동일).
SQL
복사

6. ORDER BY 의 위치 ⭐⭐

ORDER BY 는 전체 집합 연산의 맨 마지막에 딱 한 번만.
-- ============================================================ -- 【시험용 예제】 ORDER BY 는 맨 끝에 한 번 ★★ -- ============================================================ -- ✅ 올바른 위치 : 전체의 맨 마지막 SELECT ENAME, SAL FROM EMP WHERE DEPTNO = 10 UNION SELECT ENAME, SAL FROM EMP WHERE DEPTNO = 20 ORDER BY SAL DESC; -- 합쳐진 전체 결과를 정렬 -- → 두 집합을 합친 뒤 급여 내림차순으로 정렬 -- ❌ 중간 SELECT 에 ORDER BY 를 쓰면 오류 SELECT ENAME, SAL FROM EMP WHERE DEPTNO = 10 ORDER BY SAL -- 여기 쓰면 안 됨! UNION SELECT ENAME, SAL FROM EMP WHERE DEPTNO = 20; -- ORA-00933: SQL command not properly ended -- ⭐ ORDER BY 의 정렬 기준은 '첫 번째 SELECT' 의 컬럼명 또는 순번을 쓴다 SELECT ENAME AS 사원명, SAL FROM EMP WHERE DEPTNO = 10 UNION SELECT ENAME, SAL FROM EMP WHERE DEPTNO = 20 ORDER BY 사원명; -- 첫 SELECT 의 별칭 '사원명' 사용 가능 -- 또는 ORDER BY 1; (컬럼 순번)
SQL
복사
규칙
내용
위치
전체의 맨 마지막에 한 번만
중간 SELECT
ORDER BY 불가
정렬 기준
첫 번째 SELECT 의 컬럼명/별칭/순번

7. NULL과 집합 연산

-- ============================================================ -- 【시험용 예제】 집합 연산자는 NULL 을 '같은 것' 으로 취급한다 ★ -- ============================================================ SELECT COMM FROM EMP WHERE DEPTNO = 20 -- 20번: 전원 COMM 이 NULL (5명) UNION SELECT COMM FROM EMP WHERE DEPTNO = 10; -- 10번: 전원 COMM 이 NULL (3명) -- COMM -- ------ -- (NULL) → 1건! NULL 8개가 '하나' 로 합쳐진다 -- -- ⭐ 06강에서 "NULL 끼리는 비교 불가(UNKNOWN)" 라고 했지만, -- 집합 연산자(UNION/INTERSECT/MINUS)와 GROUP BY/DISTINCT 는 -- 예외적으로 NULL 을 '같은 값' 으로 취급한다. (07·11강 회수)
SQL
복사

8. 출제 포인트 한눈에 정리

#
꼭 외울 것
핵심
1
집합 연산자 4종
UNION UNION ALL INTERSECT MINUS
2
조인 vs 집합
조인=가로(컬럼) / 집합=세로(행)
3
사용 규칙
컬럼 개수·순서·타입 일치 ⭐
4
규칙 위반
ORA-01789(개수) / ORA-01790(타입)
5
컬럼명 기준
첫 번째 SELECT
6
UNION
중복 제거 + 정렬 (느림)
7
UNION ALL
중복 유지 + 정렬 안 함 (빠름) ⭐
8
성능
중복 없으면 UNION ALL 권장
9
INTERSECT
교집합 (공통)
10
MINUS
차집합, 순서 중요 (A−B ≠ B−A) ⭐
11
MINUS 타 DBMS
SQL Server는 EXCEPT
12
ORDER BY 위치
맨 마지막 한 번만 ⭐
13
ORDER BY 기준
첫 SELECT 컬럼명/순번
14
집합 연산과 NULL
NULL을 같게 취급

9. 확인 문제

Q1. 집합 연산자를 사용하기 위한 조건으로 옳지 않은 것은? ① 두 SELECT의 컬럼 개수가 같아야 한다 ② 대응하는 컬럼의 데이터 타입이 같아야 한다 ③ 컬럼 순서가 일치해야 한다 ④ 두 SELECT의 컬럼명이 완전히 같아야 한다
정답 보기
Q2. UNION 과 UNION ALL 의 차이는?
정답 보기
Q3. 두 집합의 행이 각각 6건, 5건이고 겹치는 행이 3건일 때, UNION 과 UNION ALL 의 결과 건수는?
정답 보기
Q4. A MINUS B 와 B MINUS A 의 결과가 다른 이유는?
정답 보기
Q5. 다음 두 SQL은 같은 결과를 내는가?
-- (A) SELECT ENAME FROM EMP WHERE SAL>=2000 INTERSECT SELECT ENAME FROM EMP WHERE DEPTNO=20; -- (B) SELECT ENAME FROM EMP WHERE SAL>=2000 AND DEPTNO=20;
SQL
복사
정답 보기
Q6. 두 SELECT 모두 커미션이 NULL인 행만 반환할 때, UNION 하면 NULL은 몇 건 나오는가?
정답 보기