| 연산자 | 설명 |
|---|---|
| UNION | 두 SELECT 결과를 합친 후 중복 제거 |
| UNION ALL | 두 SELECT 결과를 합치되 중복을 허용 |
| INTERSECT | 두 SELECT 결과의 교집합(공통 데이터만 출력) |
| EXCEPT | 첫 번째 SELECT 결과에서 두 번째 SELECT 결과를 제외 |
✅ 집합 연산자의 기본 규칙
1. 합칠 SELECT 문들의 열 개수와 데이터 타입이 동일해야 함
2. UNION은 자동으로 중복을 제거 (중복 제거 없이 합치려면 UNION ALL 사용)
3. ORDER BY는 마지막 SELECT 문에서만 사용 가능
-- 커리어 평균 연봉이 300만 이상인 선수
SELECT playerID
FROM salaries
GROUP BY playerID
HAVING AVG(salary) >= 3000000;
-- 12월에 태어난 선수
SELECT playerID
FROM players
WHERE birthMonth = 12;
-- 커리어 평균 연봉이 300만 이상이거나 12월에 태어난 선수
SELECT playerID
FROM salaries
GROUP BY playerID
HAVING AVG(salary) >= 3000000
UNION
SELECT playerID
FROM players
WHERE birthMonth = 12
ORDER BY playerID;
📌 UNION은 자동으로 중복을 제거하므로, 같은 선수가 두 조건을 만족해도 한 번만 출력됩니다.
-- UNION: 중복 제거
SELECT playerID
FROM salaries
GROUP BY playerID
HAVING AVG(salary) >= 3000000
UNION
SELECT playerID
FROM players
WHERE birthMonth = 12
ORDER BY playerID;
-- UNION ALL: 중복 허용
SELECT playerID
FROM salaries
GROUP BY playerID
HAVING AVG(salary) >= 3000000
UNION ALL
SELECT playerID
FROM players
WHERE birthMonth = 12
ORDER BY playerID;
📌 UNION → 중복 제거, UNION ALL → 중복 허용
✅ "보상 지급 로직" 같은 곳에서는 UNION ALL 사용 시 중복 지급 문제가 발생할 수 있음!
📌 "평균 연봉이 3백만 이상이면서 12월에 태어난 선수"
SELECT playerID
FROM salaries
GROUP BY playerID
HAVING AVG(salary) >= 3000000
INTERSECT
SELECT playerID
FROM players
WHERE birthMonth = 12
ORDER BY playerID;
✅ INTERSECT은 두 SELECT 결과에서 공통된 데이터만 반환!
📌 "평균 연봉이 3백만 이상인 선수 중에서 12월생을 제외"
SELECT playerID
FROM salaries
GROUP BY playerID
HAVING AVG(salary) >= 3000000
EXCEPT
SELECT playerID
FROM players
WHERE birthMonth = 12
ORDER BY playerID;
✅ EXCEPT은 첫 번째 SELECT 결과에서 두 번째 SELECT 결과를 빼고 출력!
✅ 1) SELECT 문들의 열 개수와 데이터 타입이 동일해야 함
-- 오류 발생 (첫 번째 SELECT에는 2개의 열, 두 번째는 1개의 열)
SELECT playerID, AVG(salary)
FROM salaries
GROUP BY playerID
HAVING AVG(salary) >= 3000000
UNION
SELECT playerID
FROM players
WHERE birthMonth = 12;
❌ 오류 해결 방법
NULL AS 컬럼명을 추가SELECT playerID, AVG(salary)
FROM salaries
GROUP BY playerID
HAVING AVG(salary) >= 3000000
UNION
SELECT playerID, NULL AS salary
FROM players
WHERE birthMonth = 12;
✅ 2) UNION 사용 시 ORDER BY는 마지막 SELECT 문에서만 가능
SELECT playerID
FROM salaries
GROUP BY playerID
HAVING AVG(salary) >= 3000000
UNION
SELECT playerID
FROM players
WHERE birthMonth = 12
ORDER BY playerID; -- ✅ 올바른 사용
SELECT playerID
FROM salaries
GROUP BY playerID
HAVING AVG(salary) >= 3000000
ORDER BY playerID -- ❌ 오류 발생
UNION
SELECT playerID
FROM players
WHERE birthMonth = 12;
✅ 중복 제거가 필요하면 UNION, 중복 허용이 필요하면 UNION ALL
✅ "교집합"을 구하려면 INTERSECT, "차집합"을 구하려면 EXCEPT
✅ ORDER BY는 마지막 SELECT 문에서만 가능
✅ 열 개수와 데이터 타입이 동일해야 함
📌 "다양한 조건을 조합하여 데이터를 효율적으로 가져오는 방법!"
JOIN과 UNION의 차이점도 추가로 다뤄볼까요? 😊