[SQLD] 집합 연산자

Shy·2024년 5월 21일

SQLD

목록 보기
19/23

집합 연산자

집합 연산자(Set Operator)는 두 개 이상의 테이블에서 조인을 사용하지 않고 연관된 데이터를 조회하는 방법 중 하나로, 여러 개의 쿼리 결과를 결합하여 하나의 결과로 만드는 방식이다.

1️⃣ 집합 연산자 종류

집합 연산자는 다음과 같은 종류가 있다.

  1. UNION: 두 개 이상의 쿼리 결과를 결합하며, 중복된 행은 제거된다.
  2. UNION ALL: 두 개 이상의 쿼리 결과를 결합하며, 중복된 행도 모두 포함된다.
  3. INTERSECT: 두 개 이상의 쿼리 결과의 교집합을 반환한다. 즉, 모든 쿼리에서 공통으로 나타나는 행만 반환된다.
  4. EXCEPT (또는 MINUS): 첫 번째 쿼리 결과에서 두 번째 쿼리 결과를 제외한 차집합을 반환한다. 순서가 중요하다.

2️⃣ 집합 연산자의 사용 제약조건

집합 연산자를 사용할 때에는 다음과 같은 제약조건이 있다.

  • SELECT 절의 칼럼 수가 동일해야 한다.
  • SELECT 절의 동일 위치에 있는 칼럼의 데이터 타입이 상호 호환 가능해야 한다 (반드시 동일한 데이터 타입일 필요는 없음).

3️⃣ 예제

1. UNION 예제

SELECT PLAYER_NAME, BACK_NO 
FROM PLAYER 
WHERE TEAM_ID = 'K02' 
UNION 
SELECT PLAYER_NAME, BACK_NO 
FROM PLAYER 
WHERE TEAM_ID = 'K07' 
ORDER BY PLAYER_NAME;
  • 첫 번째 SELECT문은 ‘K02’ 팀에 속한 선수의 이름과 백넘버를 선택한다.
  • 두 번째 SELECT문은 ‘K07’ 팀에 속한 선수의 이름과 백넘버를 선택한다.
  • UNION 연산자를 사용하여 두 결과를 결합하며 중복된 행은 제거한다.
  • ORDER BY PLAYER_NAME을 사용하여 최종 결과를 선수 이름으로 정렬한다.

이 쿼리는 ‘K02’ 팀과 ‘K07’ 팀에 속한 선수의 이름과 백넘버를 중복 없이 하나의 결과로 반환한다.

2. UNION ALL 예제

SELECT PLAYER_NAME, BACK_NO 
FROM PLAYER 
WHERE TEAM_ID = 'K02' 
UNION ALL 
SELECT PLAYER_NAME, BACK_NO 
FROM PLAYER 
WHERE TEAM_ID = 'K07' 
ORDER BY PLAYER_NAME;

이 쿼리는 ‘K02’ 팀과 ‘K07’ 팀에 속한 선수의 이름과 백넘버를 중복을 포함하여 모두 반환한다.

3. INTERSECT 예제

SELECT PLAYER_NAME, BACK_NO 
FROM PLAYER 
WHERE TEAM_ID = 'K02' 
INTERSECT 
SELECT PLAYER_NAME, BACK_NO 
FROM PLAYER 
WHERE TEAM_ID = 'K07';

이 쿼리는 ‘K02’ 팀과 ‘K07’ 팀에 모두 속한 선수의 이름과 백넘버를 반환한다.

4. EXCEPT 예제

SELECT PLAYER_NAME, BACK_NO 
FROM PLAYER 
WHERE TEAM_ID = 'K02' 
EXCEPT 
SELECT PLAYER_NAME, BACK_NO 
FROM PLAYER 
WHERE TEAM_ID = 'K07';

이 쿼리는 ‘K02’ 팀에 속해 있으나 ‘K07’ 팀에는 속하지 않은 선수의 이름과 백넘버를 반환한다.

4️⃣ 집합 연산자의 활용 상황

집합 연산자는 다음과 같은 상황에서 유용하게 사용할 수 있다.

  • 서로 다른 테이블에서 유사한 형태의 결과를 하나로 합치고자 할 때.
  • 동일 테이블에서 서로 다른 조건을 가진 쿼리 결과를 하나로 합치고자 할 때.
  • 실행 계획을 분리하여 튜닝하고자 할 때.

예제1

소속이 삼성블루윙즈팀인 선수들과 전남드레곤즈팀인 선수들에 대한 내용을 모두 보고 싶다.

SELECT TEAM_ID 팀코드, PLAYER_NAME 선수명, POSITION 포지션, BACK_NO 백넘버, HEIGHT 키 
FROM PLAYER 
WHERE TEAM_ID = 'K02' 
UNION 
SELECT TEAM_ID 팀코드, PLAYER_NAME 선수명, POSITION 포지션, BACK_NO 백넘버, HEIGHT 키 
FROM PLAYER 
WHERE TEAM_ID = 'K07';

이 SQL문은 ‘K02’팀과 ‘K07’팀 선수들의 정보를 중복 없이 반환한다.

예제2

소속이 삼성블루윙즈팀인 선수들과 포지션이 골키퍼(GK)인 선수들을 모두 보고 싶다.

SELECT TEAM_ID 팀코드, PLAYER_NAME 선수명, POSITION 포지션, BACK_NO 백넘버, HEIGHT 키 
FROM PLAYER 
WHERE TEAM_ID = 'K02' 
UNION 
SELECT TEAM_ID 팀코드, PLAYER_NAME 선수명, POSITION 포지션, BACK_NO 백넘버, HEIGHT 키 
FROM PLAYER 
WHERE POSITION = 'GK';

이 SQL문은 ‘K02’팀 선수들과 골키퍼 포지션 선수들의 정보를 중복 없이 반환한다.

예제3

포지션별 평균키와 팀별 평균키를 알고 싶다.

SELECT 'P' 구분코드, POSITION 포지션, AVG(HEIGHT) 평균키 
FROM PLAYER 
GROUP BY POSITION 
UNION 
SELECT 'T' 구분코드, TEAM_ID 팀명, AVG(HEIGHT) 평균키 
FROM PLAYER 
GROUP BY TEAM_ID 
ORDER BY 1;

아래는 위 쿼리문에 관한 결과값의 예시이다.

구분코드포지션/팀명평균키
PForward185.0
PGuard172.5
PCenter205.0
TA185.0
TB190.0

이 SQL문은 포지션별 평균 키와 팀별 평균 키를 각각 계산한 후, 그 결과를 합집합으로 반환한다.

예제4

소속이 삼성블루윙즈팀이면서 포지션이 미드필더(MF)가 아닌 선수들의 정보를 보고 싶다.

SELECT TEAM_ID 팀코드, PLAYER_NAME 선수명, POSITION 포지션, BACK_NO 백넘버, HEIGHT 키 
FROM PLAYER 
WHERE TEAM_ID = 'K02' 
MINUS 
SELECT TEAM_ID 팀코드, PLAYER_NAME 선수명, POSITION 포지션, BACK_NO 백넘버, HEIGHT 키 
FROM PLAYER 
WHERE POSITION = 'MF' 
ORDER BY 1, 2, 3, 4, 5;

이 SQL문은 ‘K02’팀 선수들 중 포지션이 미드필더(MF)인 선수들을 제외한 나머지 선수들의 정보를 반환한다.

예제5

소속이 삼성블루윙즈팀이면서 포지션이 골키퍼(GK)인 선수들의 정보를 보고 싶다.

SELECT TEAM_ID 팀코드, PLAYER_NAME 선수명, POSITION 포지션, BACK_NO 백넘버, HEIGHT 키 
FROM PLAYER 
WHERE TEAM_ID = 'K02' 
INTERSECT 
SELECT TEAM_ID 팀코드, PLAYER_NAME 선수명, POSITION 포지션, BACK_NO 백넘버, HEIGHT 키 
FROM PLAYER 
WHERE POSITION = 'GK' 
ORDER BY 1, 2, 3, 4, 5;

이 SQL문은 ‘K02’팀 선수들 중 포지션이 골키퍼(GK)인 선수들의 정보를 반환한다.

4️⃣ 각 연산자의 역할 요약

  • UNION: 두 쿼리의 결과를 합집합으로 결합, 중복 제거.
  • UNION ALL: 두 쿼리의 결과를 합집합으로 결합, 중복 포함.
  • INTERSECT: 두 쿼리의 결과의 교집합을 반환.
  • MINUS: 첫 번째 쿼리 결과에서 두 번째 쿼리 결과를 제외한 차집합을 반환 (Oracle). SQL Server에서는 EXCEPT 사용.
profile
신입사원...

0개의 댓글