데이터베이스 연구실.log

집합 연산

두 쿼리 결과를 위아래로 합치거나(UNION ALL, UNION) 공통 행(INTERSECT), 한쪽에만 있는 행(MINUS)을 구하는 집합 연산자의 규칙과 업무 활용 예

UNION ALLUNIONINTERSECTMINUS집합 연산자ROLLUPDB 링크

#핵심 요약

집합 연산자는 네 가지임
UNION ALL(합집합), UNION(합집합 + 중복 제거), INTERSECT(교집합), MINUS(차집합)

위아래 쿼리의 컬럼 수가 같아야 하고, 대응하는 컬럼은 같은 데이터 타입 그룹(숫자, 문자 등)이어야 함

집합 연산자끼리는 우선순위가 같아 왼쪽부터 평가됨
다른 순서는 괄호로 정함

실습의 활용 예: 서로 다른 집계를 한 결과로 보기, 두 테이블의 공통 고객이나 이탈 고객 찾기, 두 DB의 같은 테이블 차이 비교

#개념과 동작 원리

연산자 결과
UNION ALL 두 결과의 모든 행
중복을 없애지 않음
UNION 어느 한쪽에 있는 행을 중복 없이
INTERSECT 두 쿼리 모두에 있는 행을 중복 없이
MINUS 첫 쿼리에만 있고 둘째에는 없는 행을 중복 없이

집합 연산에서는 데이터 타입 그룹을 넘는 암시적 변환을 하지 않음
한쪽이 문자, 다른 쪽이 숫자면 오류임
한쪽 테이블에 없는 컬럼은 TO_CHAR(NULL)처럼 타입을 맞춘 NULL로 채움

ORDER BY는 맨 끝에 한 번만 씀
구성 쿼리 안에는 쓸 수 없음
앞쪽 SELECT 목록의 식으로 정렬하려면 별칭을 줌

BLOB, CLOB, BFILE, VARRAY, 중첩 테이블 컬럼에는 쓸 수 없고, UNION, INTERSECT, MINUS는 LONG 컬럼에 쓸 수 없음
FOR UPDATE와 함께 쓸 수 없음

앞으로 INTERSECT의 우선순위가 높아질 예정이므로 다른 집합 연산자와 섞을 때는 괄호를 쓰라고 권함

#필수 명령어 또는 SQL

#UNION ALL로 집계 결과 합치기

SQL Developer 또는 SQL*Plus조회만 함
SELECT deptno, SUM(sal)
  FROM emp
 GROUP BY deptno
UNION ALL
SELECT NULL, SUM(sal)
  FROM emp
 ORDER BY deptno;

결과 해석: 부서별 월급 합계 아래에 전체 합계 한 행이 붙음
실습에서는 같은 결과를 GROUP BY ROLLUP(deptno)로 얻을 수 있고, 실행 계획에서 읽은 버퍼 수가 줄어든다고 설명했음
ROLLUP은 다차원 집계에 있음

서로 다른 기준의 집계를 한 결과로 보기:

SQL Developer 또는 SQL*Plus조회만 함
SELECT deptno, TO_CHAR(NULL) AS job, SUM(sal)
  FROM emp
 GROUP BY deptno
UNION ALL
SELECT TO_NUMBER(NULL) AS deptno, job, SUM(sal)
  FROM emp
 GROUP BY job
UNION ALL
SELECT TO_NUMBER(NULL), TO_CHAR(NULL), SUM(sal)
  FROM emp
 ORDER BY deptno, job;

결과 해석:

두 배송 테이블(로켓배송, 일반배송 주문: 주문번호, 고객 이름, 상품명, 주문일)을 합쳐 배송 유형별 건수 구하기:

SQL Developer 또는 SQL*Plus조회만 함
SELECT delivery_type, COUNT(*)
  FROM (
        SELECT cust_name, item_name, '로켓배송' AS delivery_type
          FROM rocket_order
        UNION ALL
        SELECT cust_name, item_name, '일반 배송' AS delivery_type
          FROM normal_order
       )
 GROUP BY delivery_type;

결과 해석: 개별 실행 출력은 기재 없음

#INTERSECT, MINUS

실습 테이블: 회원(member), 1월, 2월 구매 이력(order_jan, order_feb), 쿠폰 대상(coupon_target), 환불 이력(refund_log), 상품 목록(product_catalog)

SQL Developer 또는 SQL*Plus조회만 함
SELECT member_id FROM order_jan
INTERSECT
SELECT member_id FROM order_feb;

SELECT member_id FROM order_jan
MINUS
SELECT member_id FROM order_feb;

SELECT member_id
  FROM coupon_target
MINUS
(
 SELECT member_id FROM order_jan
 UNION
 SELECT member_id FROM order_feb
);

결과 해석: 첫 문장은 두 달 연속 구매한 회원(충성 고객), 둘째는 1월에만 사고 2월에는 사지 않은 회원(이탈 고객), 셋째는 쿠폰을 받고 한 번도 사지 않은 회원임
셋째 문장은 괄호로 UNION을 먼저 계산함

#두 DB의 테이블 차이 비교

실습에서는 짝과 서로 DB 링크를 만들어 같은 구조의 테이블을 비교했음

SQL Developer 또는 SQL*Plus조회만 함
SELECT * FROM emp
MINUS
SELECT * FROM emp_<INITIAL>@<LINK_NAME>;

SELECT * FROM emp_<INITIAL>@<LINK_NAME>
MINUS
SELECT * FROM emp;

결과 해석: 양쪽 방향으로 실행해야 한쪽에만 있는 행과 값이 다른 행을 모두 찾음
DB 링크는 데이터베이스 링크에 있음

#사용 조건과 주의사항

바꿀 입력값: <INITIAL>, <LINK_NAME>

SEO_HKabsumveritas@gmail.comBuilt with Claude Code & Codex

마지막 갱신 개인 학습 기록이며 운영 환경 적용 전 공식 문서 확인 필요

두 글자 이상 입력, 위아래 화살표로 이동하고 Enter로 열기