Oracle DB UNION 사용 방법: 중복 제거와 UNION ALL 성능까지

Oracle에서 여러 SELECT 결과를 세로로 합칠 때는 UNION 또는 UNION ALL을 사용합니다. 먼저 중복 행을 제거해야 하는지 결정하고, 두 쿼리의 컬럼 수와 데이터 타입을 맞춘 뒤 실행계획과 결과 건수를 확인하는 순서로 작업하면 됩니다.

중복 제거가 필요하면 UNION, 각 SELECT의 결과를 그대로 합치려면 UNION ALL을 선택하세요. 특별한 중복 제거 요구가 없다면 UNION ALL이 불필요한 정렬·중복 제거 작업을 줄일 가능성이 큽니다.

상황에 맞는 경로 고르기

UNION 계열 연산은 SELECT 결과를 행 단위로 결합합니다. 각 SELECT는 같은 개수의 컬럼을 반환해야 하며, 같은 위치의 컬럼끼리는 서로 호환되는 데이터 타입이어야 합니다. 컬럼 이름은 첫 번째 SELECT의 이름이 결과 컬럼명으로 사용됩니다.

UNION

중복 행
전체 결과에서 중복 제거

일반적인 처리 부담
중복 제거를 위한 추가 작업이 발생할 수 있음

적합한 경우
집합처럼 유일한 결과가 필요할 때

주의할 점
중복으로 판단되는 행의 모든 선택 컬럼 값이 같아야 제거됨

UNION ALL

중복 행
중복 행도 유지

일반적인 처리 부담
결과 결합 중심으로 처리

적합한 경우
로그·이력·서로 겹치지 않는 범위의 결과를 합칠 때

주의할 점
원본 간 중복이 결과에 남을 수 있음

권장 실행 경로

예를 들어 2024년과 2025년 주문 테이블의 결과를 합치되, 동일한 주문 행이 양쪽에 있을 때 한 번만 표시하려면 UNION을 사용합니다. 중복을 허용하려면 같은 구조에서 UNION ALL로 바꿉니다.

  1. 각 SELECT가 반환할 컬럼의 개수와 순서를 정합니다. 컬럼명보다 위치가 중요하므로 두 쿼리의 첫 번째 컬럼끼리 같은 의미인지 확인합니다.
  2. 서로 다른 데이터 타입은 CAST 또는 적절한 변환 함수로 맞춥니다. 한쪽에만 존재하는 컬럼은 NULL을 넣고 필요한 경우 데이터 타입을 명시합니다.
  3. 중복 제거가 필요하면 UNION을, 결과를 모두 보존해야 하면 UNION ALL을 사용해 쿼리를 작성합니다.
  4. 전체 결과를 정렬해야 한다면 마지막 SELECT 뒤에 ORDER BY를 한 번만 작성합니다.
  5. 실행 후 결과 건수와 중복 여부를 확인하고, 운영 쿼리라면 실행계획에서 불필요한 정렬이나 중복 제거 작업이 있는지 점검합니다.
SELECT order_id, customer_id, order_date
FROM orders_2024
UNION
SELECT order_id, customer_id, order_date
FROM orders_2025
ORDER BY order_date, order_id;

위 쿼리에서 ORDER BY는 결합된 전체 결과에 적용됩니다. 각 SELECT 내부에 별도의 정렬을 넣는 방식은 일반적인 UNION 결과 정렬 용도로 적절하지 않으며, 정렬이 필요하면 최종 결과에 기준을 지정하는 편이 명확합니다.

SELECT order_id, customer_id, order_date
FROM orders_2024
UNION ALL
SELECT order_id, customer_id, order_date
FROM orders_2025;

UNION ALL은 두 결과를 그대로 이어 붙입니다. 두 테이블의 기간이 겹치지 않거나, 중복 행도 각각의 발생 건으로 보존해야 하는 이력·집계 원천 데이터에 적합합니다. 반대로 고객 목록처럼 동일한 행을 한 번만 보여줘야 한다면 UNION이 의도에 맞습니다.

공통 확인 방법

먼저 각 SELECT를 단독으로 실행해 컬럼 구조와 결과 건수를 확인한 뒤 UNION 쿼리를 실행합니다. 중복 제거가 의도된 경우에는 UNION과 UNION ALL의 건수를 비교하면 제거된 중복이 있는지 빠르게 파악할 수 있습니다.

SELECT COUNT(*) AS total_rows
FROM (
    SELECT order_id, customer_id, order_date FROM orders_2024
    UNION ALL
    SELECT order_id, customer_id, order_date FROM orders_2025
);

SELECT COUNT(*) AS distinct_rows
FROM (
    SELECT order_id, customer_id, order_date FROM orders_2024
    UNION
    SELECT order_id, customer_id, order_date FROM orders_2025
);

실행계획은 사용 중인 도구에서 해당 SQL의 실행계획을 표시해 확인합니다. UNION ALL은 각 입력 결과를 결합하는 흐름을, UNION은 여기에 중복 제거 단계가 추가되는지를 중점적으로 비교하세요. 단순히 UNION ALL이 항상 빠르다고 단정하기보다, 중복 제거가 업무적으로 필요한지와 실제 실행계획·처리 건수를 함께 기준으로 선택하는 것이 안전합니다.