본문 바로가기
백엔드/데이터베이스

집합 연산(UNION, UNION ALL, INTERSECT, MINUS)

by study_yeon 2023. 7. 12.

● 집합쿼리(테이블 결합하기) 

-엑셀에서 같은 종류의 테이블을 병합하는 것과 같다

1)  UNION : 집합연산의 합집합

- 중복된 데이터가 있으면 중복된 데이터가 1회만 조회된다
비교하는 컬럼이 여러개 있으면 적용이 안됨, 비교하는 컬럼이 모두 동일한 값이어야 한다
[구문]

SELECT 컬럼
    FROM 테이블명
    (WHERE 전체 테이블에 적용될 제한조건)
UNION
SELECT 컬럼
    FROM 테이블명
    (WHERE 전체 테이블에 적용될 제한조건)

'A'테이블 = 고유데이터 + 공통데이터
'B'테이블 = 고유데이터 + 공통데이터
'A'테이블 UNION 'B'테이블 = 'A'의 고유데이터 + 'B'의 고유데이터 + 공통데이터
- 컬럼의 수와 타입이 같아야함


2) UNION ALL : 합집합

- UNION + 공통데이터 
- 두 테이블의 공통된 데이터를 포함한 모든 데이터를 가지고옴
- 데이터를 그대로 유지하고 싶을때 사용
- 두 테이블을 합쳐서 한개의 테이블로 만든다
[구문]

SELECT 컬럼들...
    FROM 테이블명
    (WHERE 전체 테이블에 적용될 제한조건)
UNION ALL
SELECT 컬럼들...
    FROM 테이블명
    (WHERE 전체 테이블에 적용될 제한조건)

* 주의점 : 
- 첫번째 테이블과 두번째 테이블은 데이터 순서와 데이터형이 동일해야한다(컬럼명은 동일하지 않아도 됨)
- 조회 결과는 첫번째 테이블의 컬럼명을 기준으로 한다
- 결과테이블(SELECT질의 결과를 VIEW라고 한다)을 정렬할 때 첫번째 테이블의 컬럼 이름을 사용(별명 이용 안됨)


3) 교집합(INTERSECT)

- 두 테이블 사이의 공통된 원소만 추출하는 교집합과 같은 집합쿼리
- 두 개의 쿼리를 검색해서 공통된 요소만 결과로 가져온다
- UNION과 다른점은 오직 중복된 데이터만 추출한다는 것
[구문]

SELECT 비교할 컬럼리스트
   FROM 테이블1
INTERSECT 
SELECT 비교할 컬럼리스트
   FROM 테이블2;


4) 차집합(MINUS)

- 테이블 A와 B의 차집합은 A - B = A테이블의 고유데이터만 검색하여 가져오는 경우
- A - B = A의 데이터 - 공통데이터 = A의 고유 데이터
- 첫 번째 결과에서 두 번째 결과집합의 공통데이터를 뺀다
[구문]

SELECT 컬럼 
   FROM 테이블
 MINUS
SELECT 컬럼 
   FROM 테이블

 


▶ 실습

 

◎ 집합 연산자에 사용할 테이블 생성하기

-- A테이블
CREATE TABLE MEMBER (
	mem_id     NUMBER        NOT NULL,
	mem_name   varchar2(100) NOT NULL,
	gender     varchar2(100),
	age        NUMBER,
	hire_date  DATE,
	etc        varchar2(500),
	CONSTRAINT mem_pk PRIMARY KEY (mem_id)
);
-- B테이블
CREATE TABLE employee (
	emp_id NUMBER NOT NULL,
	emp_name VARCHAR2(100) NOT NULL,
	gender VARCHAR2(10) NULL,
	age NUMBER NULL,
	hire_date DATE NULL,
	etc VARCHAR2(500) NULL,
	PRIMARY KEY(emp_id)
);

◎ 데이터 추가하기

-- A(member)테이블에 데이터 추가하기
INSERT INTO MEMBER (mem_id, mem_name, gender, age, hire_date)
  values(1, '선덕여왕', '여성', 23, to_date('2023-02-01', 'YYYY-MM-DD'));
INSERT INTO MEMBER (mem_id, mem_name, gender, age, hire_date)
  values(2, '허난설현', '여성', 33, to_date('2023-02-01', 'YYYY-MM-DD'));
INSERT INTO MEMBER (mem_id, mem_name, gender, age, hire_date)
  values(3, '김만덕', '남성', 43, to_date('2023-02-01', 'YYYY-MM-DD'));
INSERT INTO MEMBER (mem_id, mem_name, gender, age, hire_date)
  values(4, '장희빈', '여성', 35, to_date('2023-02-01', 'YYYY-MM-DD'));
INSERT INTO MEMBER (mem_id, mem_name, gender, age, hire_date)
  values(5, '신사임당', '여성', 45, to_date('2023-02-01', 'YYYY-MM-DD'));

-- B(employee)테이블에 데이터 추가하기
INSERT INTO employee(emp_id, emp_name, gender, age, hire_date)
	VALUES(1, '홍길동', '남성', 33, '2023-03-03');
INSERT INTO employee(emp_id, emp_name, gender, age, hire_date)
	VALUES(2, '김유신', '남성', 44, '2023-04-04');
INSERT INTO employee(emp_id, emp_name, gender, age, hire_date)
	VALUES(3, '강감찬', '남성', 55, '2023-05-05');
INSERT INTO employee(emp_id, emp_name, gender, age, hire_date)
	VALUES(4, '신사임당', '여성', 45, '2023-06-06');
INSERT INTO EMPLOYEE (emp_id, emp_name, gender, age, hire_date)
	VALUES (5,'세종대왕', '남성', 46, '2022/07/07');


1. UNION

/* 합집합 */
-- 1. UNION 
SELECT e.EMP_NAME
	FROM EMPLOYEE e
 UNION
SELECT m.MEM_NAME
	FROM MEMBER m;

중복값인 신사임당 하나만 출력


2. UNION ALL

/* 합집합 */
-- 2. UNION ALL
SELECT e.EMP_ID, e.EMP_NAME, e.GENDER, e.AGE
	FROM EMPLOYEE e
 UNION ALL
SELECT m.MEM_ID, m.MEM_NAME, m.GENDER, m.AGE 
	FROM MEMBER m
ORDER BY EMP_ID;

중복값인 신사임당이 모두 출력됨


3. INTERSECT

/* 교집합 */
-- 3. INTERSECT
SELECT e.EMP_NAME
	FROM EMPLOYEE e
 INTERSECT
SELECT m.MEM_NAME 
	FROM MEMBER m;

-- 비교할 컬럼의 수가 늘어난 경우(동일한 값이 없어서 추출이 안됨)
SELECT m.MEM_ID, m.MEM_NAME 
	FROM MEMBER m
 INTERSECT
SELECT e.EMP_ID, e.EMP_NAME
	FROM EMPLOYEE e;

동일한 값이 없어서 추출이 안됨


4. MINUS

/* 차집합 */
-- 4. MINUS
-- EMPLOYEE 테이블에만 속하는 사람 구하기
SELECT EMP_NAME 
	FROM EMPLOYEE e 
 MINUS
SELECT MEM_NAME
	FROM "MEMBER" m;

-- EMPLOYEE 테이블과 MEMBER 테이블 둘 중에 하나만 가입되어있는 이름 구하기
-- 두 테이블 이름에 대하여 합집합하고 그 중에 교집합을 제거
(SELECT EMP_NAME
	FROM EMPLOYEE
 UNION 
SELECT mem_name
	FROM "MEMBER")
MINUS 
(SELECT EMP_NAME
	FROM EMPLOYEE
 INTERSECT
SELECT mem_name
	FROM "MEMBER"
);

신사임당 제외