UNION

WAS·2025년 9월 24일
0

SQL

목록 보기
3/7

이전에 정리한 JOIN서브쿼리 의 공통점은 기존 테이블의 정보를 조합하거나 필터링해서
원하는 형태의 하나의 결과 집합으로 만들어 낸다는 점이다

JOIN 은 테이블을 옆으로 이어붙여서 더 많은 정보들의 컬럼들을 만드는 기술이면
이번에 정리할 UNION 은 여러개의 결과 집합을 아래로 이어 붙여서 더 많은 행을 가진
하나의 집합으로 만드는 기술이다

✅ UNION

  • 흩어진 집합들을 하나로 만드는 기술
  • JOIN 과 달리 테이블들이 서로 연결된 관계가 아닐 때 사용

UNION 을 사용할 때는 다음과 같은 규칙이 있다

  • UNION 으로 연결되는 모든 SELECT 문은 컬럼의 개수가 동일해야한다 (컬럼이름은 달라도됨)
  • SELECT 문의 같은 위치에 있는 컬럼들은 서로 호환이 가능한 데이터 타입이어야 한다
  • 최종 결과의 컬럼 이름은 첫 번째 SELECT 문의 컬럼 이름을 따른다
  • 두 결과를 합친뒤 중복되는 행은 하나만 빼고 제거된다
SELECT name, email FROM users // 컬럼 개수가 동일하고 각 컬럼들이 동일한 데이터 타입임
UNION
SELECT name, email FROM retired_users;
select user_id ,email from users u // 컬럼이 달라도되고, 같은 데이터 타입이기만 하면 합치기 가능
union 
select id,name from retired_users ru;

아래 결과처럼 중복이 제거되는 것은 합치는 모든 컬럼이 동일할때만 제거된다
1, Sean@example.com -> 두개가 중복되어서 제거됨
1, sean@example.com 과 , 1, 션 은 다른 행으로 인식되기 때문에 제거 X


✅ UNION ALL

  • UNION 과 다르게 중복되는 행을 제거하지 않고 모두 이어붙임

마케팅팀에서 두 종류의 고객에게 이벤트 안내 메일을 보내려고 한다. 첫 번째 그룹은 '전자기기' 카테고리의 상품을 구매한 이력이 있는 고객이고, 두 번째 그룹은 '서울'에 거주하는 고객이다. 두 그룹의 명단을 합쳐서 전체 발송 목록을 만든다 했을 때 문제가 있다고 하자

위와 같은 비즈니스 요구사항에서는 서울에 살면서 전가기기를 구매한 고객 은 두 그룹에 모두 속하기 때문에 중복을 허용해야한다

select u.name , u.email
  from users u
  join orders o 
    on u.user_id = o.user_id 
  join products p 
    on p.product_id = o.product_id 
 where p.category = '전자기기'
union all
select u.name, u.email 
  from users u
 where u.address like '서울%';

그럼 실무에서는 UNION vc UNION ALL 중에 어떤것을 사용할까?

UNION ALLUNION 보다 속도가 빠르다
그 이유는 UNION 은 데이터베이스 내부적으로 중복을 제거하기 위해 전체 결과를 정렬한 다음
인접한 행들을 비교하여 중복을 찾아내는 과정을 거친다
만약 데이터 양이 많다면 이 정렬과 비교 작업은 엄청난 성능 저하가 발생한다

따라서 중복을 제거해야하는 명확한 요구사항이 있을때만 UNION 을 사용하자
그 외의 모든 경우는 UNION ALL 을 우선적으로 사용하자


✅ UNION 정렬

UNIONUNION ALL 을 사용하여 행을 합칠 때 최종 결과 집합에 대해서 정렬이 가능하다

SELECT 문에 정렬 (ORDER BY) 를 사용할 수는 있지만, 예상과 다른 결과가 발생하거나 오류가 생긴다
그러므로 개별적인 정렬이아닌 합쳐진 최종 결과에 대해서 맨 마지막에 ORDER BY 를 사용하자

SELECT name, email FROM users
UNION
SELECT name, email FROM retired_users 
ORDER BY name; -- 최종 결과에 대한 정렬

UNIONUNION ALL 을 사용하여 합치면 최종결과는 항상 첫번째 SELECT 문의 컬럼이름이나
별칭만을 사용할 수 있다

SELECT name, email, created_at FROM users
UNION ALL
SELECT name, email, retired_date FROM retired_users 
ORDER BY retired_date; -- (x)

SELECT name, email, created_at FROM users 
UNION ALL // created_at 과 retired_date 와 같이 다른이름의 컬럼이 있으면 항상 추상적인 별칭으로 통일하자
SELECT name, email, retired_date FROM retired_users 
ORDER BY created_at; -- (o)
profile
우측 상단 햇님모양 클릭하셔서 무조건 야간모드로 봐주세요!!

0개의 댓글