SQLD: SQL 활용, 서브쿼리
SQLD 활용
SQLD의 2과목의 SQLD활용의 세부과목으로는 다음이 있다:
- 서브쿼리
- 집합연산자
- 그룹함수
- 윈도우함수
- TOP-N 쿼리
- 계층형 질의와 셀프 조인
- PIVOT절과 UNPIVOT절
- 정규표현식
서브쿼리
서브쿼리란 작성된 쿼리 내부에 다른 쿼리를 삽입하여, 보다 다양하게 데이터를 출력하는 방법을 의미한다.
스칼라 서브쿼리 (SELECT)
SELECT에서 사용되는 서브쿼리로, 하나의 컬럼에 대해 하나의 행만 반환하는 특징을 갖는다. 출력되는 하나의 값이 없다면 NULL을 반환한다.
실행 원리
메인쿼리에서 출력되는 튜플의 수만큼 SELECT에 있는 서브쿼리가 반복 실행된다.
1
2
3
4
5
6
7
8
9
10
SELECT A.직원ID
, A.연봉
, A.부서ID
, (
SELECT 부서병
FROM 부서
WHERE 부서ID = A.부서ID
) AS 부서명
FROM 직원 A
WHERE 직원ID BETWEEN 'A0001' AND 'A0006';
스칼라 서브쿼리는 하나의 행과 하나의 컬럼만 반환해야 한다. (한 값)
스칼라 서브쿼리는 아우터 조인으로 변경이 가능하다.
인라인 뷰 (FROM)
FROM 부분에서 사용되는 서브쿼리로, 쿼리를 작성해 가상의 테이블을 동적으로 생성해 사용할 수 있다.
1
2
3
4
5
6
7
8
9
10
11
12
SELECT A.직원ID
, A.이름
, A.연봉
FROM 직원 A
, (
SELECT 부서ID, MAX(연봉) AS 부서별최고연봉
FROM 직원
WHERE 부서ID IS NOT NULL
GROUP BY 부서ID
) B
WHERE A.부서ID = B.부서ID
AND A.연봉 = B.부서별최고연봉;
중첩서브쿼리 (WHERE)
WHERE 부분에서 주로 사용되는 서브쿼리로, 메인쿼리와 관계가 있는지에 따라 상관 서브쿼리와 비상관 서브쿼리로 나뉜다.
1
2
3
4
5
SELECT *
FROM 직원
WHERE 연봉 >= ( SELECT AVG(연봉)
FROM 직원
);
비상관 서브쿼리
서브쿼리에서 메인쿼리의 컬럼을 사용하지 않는 서브쿼리를 의미한다.
이 경우, 서브쿼리가 먼저 실행되고 메인쿼리가 실행된다.
1
2
3
4
5
SELECT *
FROM 직원
WHERE 연봉 >= ( SELECT AVG(연봉)
FROM 직원
);
비상관 서브쿼리 예시
상관 서브쿼리
서브쿼리에서 메인쿼리의 컬럼을 사용하는 서브쿼리를 의미한다.
메인쿼리에서 출력되는 행의 수만큼 서브쿼리가 실행되고, 그 결과를 대입해 메인쿼리를 실행한다.
1
2
3
4
5
6
7
SELECT *
FROM 직원
WHERE 성별 = '남'
AND 연봉 = (SELECT MIN(연봉)
FROM 직원
WHERE 부서ID = A.부서ID
);
WHERE절에서 서브쿼리 결과를 받을 때 단일행을 받을 수 있는 연산자와 다중행을 받을 수 있는 연산자가 별개이다.
’=’는 단일행만 받을 수 있고, IN은 0개, 1개, 2개…등 0개 이상을 받는다.
- IN은 입력된 다중행 중에서 일치하는 값들을 모두 출력한다.
- ANY는 입력된 다중행 중에 하나라도 일치하면 출력한다.
- ALL은 입력된 다중행이 모두 일치해야 한다.
EXISTS 연산자
EXISTS 문법:
직원 중 연락처가 있는 대상을 찾아보기:
1
2
3
4
5
6
7
SELECT 직원ID, 이름
FROM 직원 A
WHERE EXISTS (
SELECT 1
FROM 직원연락처
WHERE 직원ID = A.직원ID
);
- WHERE 뒤에 특정 컬럼을 입력하지 않고 바로
EXISTS
를 입력한다 - SELECT 뒤에 컬럼은 의미 없다 (아무거나 가능)
- 직원연락처의 직원ID와 직원 테이블 (A.직원ID)가 같은 대상을 찾는다
- 상관서브쿼리와 비슷하게 메인쿼리의 컬럼을 참조한다
NOT EXISTS 문법:
직원 중 연락처가 없는 대상을 찾아보기:
1
2
3
4
5
6
7
SELECT 직원ID, 이름
FROM 직원 A
WHERE NOT EXISTS (
SELECT 1
FROM 직원연락처
WHERE 직원ID = A.직원ID
);
- WHERE 뒤에 특정 컬럼을 입력하지 않고 바로
EXISTS
를 입력한다 - SELECT 뒤에 컬럼은 의미 없다 (아무거나 가능)
- 직원연락처의 직원ID와 직원 테이블 (A.직원ID)가 같을 경우 출력하지 않는다
- 상관서브쿼리와 비슷하게 메인쿼리의 컬럼을 참조한다