[SQL] UNION과 UNION ALL — 중복을 지워도 되는 데이터인가요?

차곡코딩·어제

SQL · 집계 쿼리

목록 보기
5/5

두 테이블의 조회 결과를 합칠 때 UNION과 UNION ALL을 사용할 수 있습니다. 선택 기준은 단순히 “중복이 있느냐”가 아니라 같은 값의 행이 서로 다른 기록을 뜻할 수 있느냐입니다.

예제는 SQLite에서 실행했습니다. 온라인과 오프라인에서 발생한 구매 금액을 합치는 상황입니다.

같은 금액의 구매도 별개의 기록입니다

CREATE TABLE online_sales (amount INTEGER NOT NULL);
CREATE TABLE offline_sales (amount INTEGER NOT NULL);

INSERT INTO online_sales VALUES (1000), (2000);
INSERT INTO offline_sales VALUES (1000), (3000);

1000원 구매가 양쪽에 한 건씩 있습니다. 금액은 같아도 총 네 번의 구매입니다.

SELECT amount FROM online_sales
UNION ALL
SELECT amount FROM offline_sales
ORDER BY amount;

결과는 1000, 1000, 2000, 3000입니다. UNION ALL은 각 조회 결과의 행을 중복 제거 없이 합칩니다.

UNION은 조회한 행 전체를 기준으로 중복을 제거합니다

SELECT amount FROM online_sales
UNION
SELECT amount FROM offline_sales
ORDER BY amount;

이번 결과는 1000, 2000, 3000입니다. 조회한 열이 amount 하나이므로 같은 금액의 두 행이 하나로 합쳐졌습니다.

두 열을 조회했다면 두 열의 값이 모두 같은 행이 중복 제거 대상입니다. UNION이 실제 구매의 동일성을 판단하거나 기본키를 알아서 찾아 비교하는 것은 아닙니다.

연산결과 행 수금액 합계
UNION ALL47000
UNION36000

서로 다른 구매를 합산하려는 상황에서 UNION을 쓰면 실제 금액보다 적게 집계될 수 있습니다.

합친 결과를 집계할 때도 기준은 같습니다

WITH all_sales AS (
    SELECT amount FROM online_sales
    UNION ALL
    SELECT amount FROM offline_sales
)
SELECT COUNT(*) AS sale_count, SUM(amount) AS total_amount
FROM all_sales;

결과는 sale_count = 4, total_amount = 7000입니다. 반대로 “구매에 사용된 서로 다른 금액의 목록”이 목적이라면 UNION이 적절할 수 있습니다.

두 SELECT는 열 개수가 같아야 하고, 같은 위치의 열끼리 의미와 자료형을 맞춰야 합니다. 이 예제는 모두 정수 금액으로 통일했습니다. 결과의 순서가 필요하면 전체 쿼리 끝에 ORDER BY를 명시합니다.

성능만 보고 무조건 하나를 선택하기보다, 결과의 한 행이 무엇을 의미해야 하는지부터 정하는 것이 우선입니다. 중복 제거가 불필요한 거래 내역에는 UNION ALL을, 서로 다른 값의 목록이 필요할 때는 UNION을 검토할 수 있습니다.

참고: SQLite 공식 문서 — Compound SELECT

profile
비전공자의 개발 성장 기록. 바이브코딩 프리랜서 경험부터 Python·SQL·AI 서비스 개발까지

0개의 댓글