🧩 JOIN vs UNION: 수평 결합과 수직 결합
먼저, JOIN과 UNION의 근본적인 차이를 이해하는 것이 중요하다.
- JOIN:
- 여러 테이블을 옆으로(수평으로) 이어 붙여, 더 많은 열(Column)을 가진 하나의 결과 집합을 만든다.
- 즉, 데이터의 정보를 풍성하게 만드는 기술이다.
- UNION:
- 여러 SELECT 문의 결과 집합을 아래로(수직으로) 이어 붙여, 더 많은 행(Row)을 가진 하나의 결과 집합을 만든다.
- 즉, 흩어진 집합들을 하나로 모으는 기술이다.
⚠️ 주의: UNION 규칙
- UNION 으로 연결되는 모든 SELECT 문은 컬럼의 개수가 동일해야 한다.
- 각 SELECT 문의 같은 위치에 있는 컬럼들은 서로 호환 가능한 데이터 타입이어야 한다.
- 최종 결과의 컬럼 이름은 첫 번째 SELECT 문의 컬럼 이름을 따른다.
예시: "활동 고객과 탈퇴 고객 모두에게 이메일을 보내기 위해, 두 테이블에 흩어진 이름과 이메일을 하나의 목록으로 만들기"
SELECT name, email FROM users
UNION
SELECT name, email FROM retired_users;
이처럼 구조는 비슷하지만 서로 다른 테이블의 데이터를 합쳐야 할 때 UNION을 사용한다.
🧩 UNION vs UNION ALL: 중복 처리의 차이와 성능
UNION과 UNION ALL의 유일한 차이점은 중복된 행을 처리하는 방식이다.
- UNION (중복 자동 제거)
- UNION은 두 결과 집합을 합친 뒤, 완전히 중복되는 행을 자동으로 제거하여 고유한 값만 남긴다.
- 예를 들어, '나중복' 고객이 users와 retired_users 테이블 양쪽에 모두 존재하더라도, 최종 결과에는 한 번만 포함된다.
- UNION ALL (중복 허용)
- UNION ALL은 중복 제거 과정 없이, 두 결과 집합을 그대로 모두 합친다.
- 예를 들어, '나중복' 고객이 users와 retired_users 테이블 양쪽에 모두 존재하면, 최종 결과에 두 번 포함된다.
✅ 실무에서는 UNION ALL을 우선 사용하라
UNION은 중복을 제거하기 위해 내부적으로 전체 결과를 정렬하고 비교하는 추가적인 작업을 수행해야 하므로, 데이터의 양이 많아질수록 성능이 크게 저하될 수 있다.
하지만 UNION ALL은 그런 과정 없이 그대로 합치므로, UNION ALL이 UNION보다 훨씬 빠르다.
따라서 중복이 없는 고유한 목록이 반드시 필요할 때만 UNION을 사용하고,
그 외 모든 경우(중복이 없음을 알거나 중복이 허용되어도 상관없는 경우)에는 성능을 위해 항상 UNION ALL을 우선적으로 사용해야 한다.
🧩 UNION 결과 정렬하기 (ORDER BY)
UNION으로 합친 최종 결과 집합을 정렬할 때는 다음과 같은 규칙을 따라야 한다.
- ORDER BY 절은 전체 UNION 쿼리의 가장 마지막에 한 번만 사용해야 한다.
- ORDER BY 절에서는 첫 번째 SELECT 문의 열 이름이나 별칭(Alias)만 사용할 수 있다.
- 이는 위에서 언급했듯이, 최종 결과 집합의 열 이름이 첫 번째 SELECT 문을 따르기 때문이다.
-- 오류 발생하는 코드
SELECT name, email, created_at FROM users
UNION ALL
SELECT name, email, retired_date FROM retired_users
ORDER BY retired_date; -- 첫 번째 SELECT 문에 없는 컬럼
created_at과 retired_date처럼 의미는 같지만 이름이 다른 열을 합칠 때는, event_date와 같이 공통된 별칭을 사용하는 것이 좋다.
SELECT name, email, created_at AS event_date FROM users
UNION ALL
SELECT name, email, retired_date AS event_date FROM retired_users
ORDER BY event_date DESC; -- 공통된 별칭을 사용하여 정렬
이렇게 하면 ORDER BY event_date와 같이 코드를 더 명확하고 일관성 있게 작성할 수 있다.
'DB' 카테고리의 다른 글
| [DB] 뷰 (VIEW) (1) | 2025.09.19 |
|---|---|
| [DB] CASE 문 (0) | 2025.09.19 |
| [DB] 서브쿼리 – 스칼라 서브쿼리, 다중 행/열 서브쿼리, 상관 서브쿼리 (0) | 2025.09.19 |
| [DB] 외부 조인 (OUTER JOIN), 셀프 조인 (SELF JOIN), 크로스 조인 (CROSS JOIN) (0) | 2025.09.19 |
| [DB] 내부 조인 (INNER JOIN) (0) | 2025.09.17 |