습관처럼

SQL 활용 - 제 2절 집합 연산자 본문

Certification/Sqld

SQL 활용 - 제 2절 집합 연산자

dev.wookii 2020. 2. 11. 17:50

1.집합 연산자(SET_OPERATOR)

  • 연관된 데이터를 조회하는 방법 중 하나
  • 여러 개의 질의의 결과를 연결하여 하나로 결합하는 방식 사용

 , 집합 연산자는 2개 이상의 질의 결과를 하나의 결과로 만들어 준다

 

일반적으로 집합 연산자를 사용하는 상황

  • 서로 다른 테이블에서 유사한 형태의 결과를 반환하는 것을 하나의 결과로 합치고자 할 때 사용
  • 동일 테이블에서 서로 다른 질의를 수행하여 결과를 합치고자 할 때 사용
  • 이외에도 튜닝관점에서 실행계획을 분리하고자 하는 목적으로도 사용 

집합 연산자를 사용하기 위한 제약조건 (조건을 지키지 않을 시 데이터베이스가 오류 반환)

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

 

문법

SELECT 칼럼명1, 칼럼명2, ... 
FROM 테이블명1 
[WHERE 조건식 ] [[GROUPBY 칼럼(Column)이나 표현식 [HAVING 그룹조건식 ] ] 

집합 연산자 

SELECT 칼럼명1, 칼럼명2, ... 
FROM 테이블명2 
[WHERE 조건식 ] [[GROUP BY 칼럼(Column)이나 표현식 [HAVING 그룹조건식 ] ] 
[ORDERBY 1, 2 [ASC 또는 DESC ] ; 

예제

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 1;

 

  • 집합 연산자는 사용상의 제약조건을 만족한다면 어떤 형태의 SELECT문이라도 이용가능
  • 집합 연산자는 여러 개의 SELECT문을 연결하는 것에 지나지 않음
  • ORDER BY는 집합 연산을 적용한 최종 결과에 대한 정렬 처리이므로 가장 마지막 줄에 한번만 기술

 

예제 1 - 'UNION' vs 'OR 연산자' / 'IN List'

질문 : K-리그 소속 선수들 중에서 소속이 삼성블루윙즈팀인 선수들과전남드레곤즈팀인 선수들에 대한 내용을 모두 보고 싶다

집합 : K-리그 소속 선수 중 소속이 삼성블루윙즈팀인 선수들의 집합과 K-리그 소속 선수 중 소속이 전남드레곤즈팀인 선수들의 집합의 합집합

쿼리 : 

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'
===================================
SELECT TEAM_ID 팀코드, PLAYER_NAME 선수명, POSITION 포지션, BACK_NO 백넘버, HEIGHT 키
FROM PLAYER
WHERE TEAM_ID = 'K02' OR TEAM_ID = 'K07'
>>비교 쿼리
===================================
SELECT TEAM_ID 팀코드, PLAYER_NAME 선수명, POSITION 포지션, BACK_NO 백넘버, HEIGHT 키
FROM PLAYER
WHERETEAM_ID IN ('K02', 'K07')
>>비교 쿼리

 

예제 2 - 'UNION' vs 'UNION ALL'

질문: K-리그 소속 선수들 중에서 소속이 삼성블루윙즈팀인 선수들과포지션이 골키퍼(GK)인 선수들을 모두 보고 싶다.

집합: K-리그 소속 선수 중 소속이 삼성블루윙즈팀인 선수들의 집합과 K-리그 소속 선수 중 포지션이 골키퍼(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'
===================================
SELECT TEAM_ID 팀코드, PLAYER_NAME 선수명, POSITION 포지션, BACK_NO 백넘버, HEIGHT 키
FROM PLAYER
WHERE TEAM_ID = 'K02'

UNION ALL

SELECT TEAM_ID 팀코드, PLAYER_NAME 선수명, POSITION 포지션, BACK_NO 백넘버, HEIGHT 키
FROM PLAYER
WHERE POSITION = 'GK'
>>비교 쿼리

 

 

예제 3 - 각 집합의 구분

질문: K-리그 소속 선수들에 대한 정보 중에서 포지션별 평균키와 팀별 평균키를 알고 싶다.

집합: K-리그 소속 선수 중 포지션별 평균키에 대한 집합과K-리그 소속 선수 중 팀별 평균키에 대한 집합의 합집합

쿼리:

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

 

 

예제 4 - 'MINUS'('EXCEPT') vs '<>' / 'NOT EXISTS 서브쿼리' / 'NOT IN 서브쿼리'

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

집합: K-리그 소속 선수 중 소속이 삼성블루윙즈팀인 선수들의 집합과 K-리그 소속 선수 중 포지션이 미드필더(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
=========================================
SELECT TEAM_ID 팀코드, PLAYER_NAME 선수명, POSITION 포지션, BACK_NO 백넘버, HEIGHT 키
FROM PLAYER
WHERE TEAM_ID = 'K02' AND POSITION <> 'MF'
ORDER BY 1, 2, 3, 4, 5
>>비교쿼리
==========================================
SELECT TEAM_ID 팀코드, PLAYER_NAME 선수명, POSITION 포지션, BACK_NO 백넘버, HEIGHT 키
FROM PLAYER X
WHERE X.TEAM_ID = 'K02' AND
        NOT EXISTS(SELECT 1 
        			FROM PLAYER Y 
                    WHERE Y.PLAYER_ID = X.PLAYER_ID 
                    	AND POSITION = 'MF')
ORDER BY 1, 2, 3, 4, 5
>>비교쿼리
==========================================
SELECT TEAM_ID 팀코드, PLAYER_NAME 선수명, POSITION 포지션, BACK_NO 백넘버, HEIGHT 키
FROM PLAYER
WHERE TEAM_ID = 'K02' AND
        PLAYER_ID NOT IN(SELECT PLAYER_ID 
        					FROM PLAYER 
                            WHERE POSITION = 'MF')
ORDER BY 1, 2, 3, 4, 5
>>비교쿼리

 

 

예제 5 - 'INTERSECT' vs 'AND =' / 'EXISTS 서브쿼리' / 'IN List 서브쿼리'

질문: K-리그 소속 선수들 중에서 소속이 삼성블루윙즈팀이면서 포지션이 골키퍼(GK)인 선수들의 정보를 보고 싶다

집합: K-리그 소속 선수 중 소속이 삼성블루윙즈팀인 선수들의 집합과 K-리그 소속 선수 중 포지션이 골키퍼(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

=====================================
SELECT TEAM_ID 팀코드, PLAYER_NAME 선수명, POSITION 포지션, BACK_NO 백넘버, HEIGHT 키
FROM PLAYER
WHERE TEAM_ID = 'K02' AND POSITION = 'GK'
ORDER BY 1, 2, 3, 4, 5
>>비교쿼리
=====================================
SELECT TEAM_ID 팀코드, PLAYER_NAME 선수명, POSITION 포지션, BACK_NO 백넘버, HEIGHT 키
FROM PLAYER X
WHERE X.TEAM_ID = 'K02' AND
        EXISTS(SELECT 1 
        		FROM PLAYER Y 
                WHERE Y.PLAYER_ID = X.PLAYER_ID AND Y.POSITION = 'GK')
ORDER BY 1, 2, 3, 4, 5
>>비교쿼리
=====================================
SELECT TEAM_ID 팀코드, PLAYER_NAME 선수명, POSITION 포지션, BACK_NO 백넘버, HEIGHT 키
FROM PLAYER
WHERE TEAM_ID = 'K02' AND
        PLAYER_ID IN(SELECT PLAYER_ID 
        				FROM PLAYER 
                        WHERE POSITION = 'GK')
ORDER BY 1, 2, 3, 4, 5 

 

 

출처: http://www.bysql.net