지극히 개인적인 공부 노트/데이터베이스(Database)

[SQL] 서브 쿼리와 서브 쿼리의 분류(feat. 반환, 위치에 따른 분류)

AS J 2021. 9. 24. 13:16

1. 서브 쿼리란?

서브 쿼리는 하나의 쿼리(메인 쿼리) 안에 포함된, 종속되는 또 하나의 쿼리를 의미한다.

알고 있지 못한 기준을 이용한 검색에 유용하고, 메인 쿼리가 실행되기 이전에 한 번만 실행되며, 한 문장에서 여러 번 사용이 가능( ex) 서브 쿼리의 서브 쿼리)하다. 사용 예시와 주의 사항은 아래와 같다.

-- 예시. 특정 사원(A)의 급여보다 높은 급여를 받는 사원 조회
-- 1. 기존 메인 쿼리만을 이용한 방법
SELECT * FROM employee WHERE 급여 > 2500;  -- 특정 사원의 급여를 알고 있는 상태에서 가능

-- 2. 서브 쿼리를 이용한 방법
SELECT * FROM employee WHERE 급여 >
(SELECT 급여 FROM employee WHERE 이름='A');  -- 특정 사원의 급여를 알지 못해도 가능
사용 시 주의 사항

1) 서브 쿼리는 괄호와 함께 사용되어야 한다.

2) 서브 쿼리 안에서 ORDER BY절은 사용할 수 없다.

3) 서브 쿼리는 연산자의 오른쪽에 사용되어야 한다.

4) 서브 쿼리는 오로지 SELECT문으로만 작성할 수 있다.

 

 

2. 서브 쿼리의 분류

1) 반환에 따른 분류

: 서브 쿼리에서 반환하는 데이터의 형태에 따른 분류를 의미하며, 단일 행 서브 쿼리, 다중 행 서브 쿼리가 있다.

(1) 단일 행 서브 쿼리: 결과로써 한 행, 1개의 값만 반환하고, 이 결과를 메인 쿼리로 전달하는 서브 쿼리이다. 비교 연산자(>, <, >=, <=, =, !=)와 함께 사용된다.

(2) 다중 행 서브 쿼리: 결과로써 2개 이상의 행이나 값을 반환하고, 이 결과를 메인 쿼리로 전달하는 서브 쿼리이다. IN, ANY, ALL 등의 연산자와 함께 사용된다.

- IN: 하나라도 만족하면 반환

- ANY: 하나라도 만족하면 반환. 비교 연산이 가능하며, 서브 쿼리 결과에 대해 내부적으로 모두 OR 연산을 수행.

- ALL: 모두 만족하면 반환. 비교 연산이 가능하며, 서브 쿼리 결과에 대해 내부적으로 모두 AND 연산을 수행.

-- 직원들의 근무 시작 일자(work_start_date), 급여(salary)를 저장한 테이블(salaries)을 예시로 들자.
-- salaries 테이블에서 work_start_date가 2000-01-01 이전인 사람들의 급여 중 하나의 급여 보다 더 적은 급여를 받은 직원의 급여 정보를 모두 출력해보세요.
SELECT * FROM salaries WHERE salary <ANY
(SELECT salary FROM salaries WHERE work_start_date < '2000-01-01');
-- 즉, ANY는 아래와 같은 결과를 의미한다.
-- <ANY: < (다중 행 서브 쿼리 결과 중 최대값)
-- >ANY: > (다중 행 서브 쿼리 결과 중 최소값)

-- salaries 테이블에서 work_start_date가 2000-01-01 이전인 사람들의 급여 중 모든 급여보다 적은 급여를 받은 직원의 급여 정보를 모두 출력해보세요.
SELECT * FROM salaries WHERE salary <ALL
(SELECT salary FROM salaries WHERE work_start_date < '2000-01-01');
-- 즉, ALL은 아래와 같은 결과를 의미한다.
-- <ALL: < (다중 행 서브 쿼리 결과 중 최소값)
-- >ALL: > (다중 행 서브 쿼리 결과 중 최대값)

 

2) 위치에 따른 분류

: 서브 쿼리의 위치에 따른 분류를 의미하며, 일반적은 서브 쿼리와 스칼라 서브 쿼리가 있다.

(1) (일반적인) 서브 쿼리: 메인 쿼리의 끝(보통 WHERE문)에 위치하며, 1번에서 사용한 예시처럼 사용된다.

(2) 스칼라 서브 쿼리: 메인 쿼리의 시작(SELECT문의 컬럼 부분)에 위치하며, 오로지 한 행, 1개의 값을 반환한다. JOIN을 사용한 것과 같은 결과를 나타낸다. 데이터가 많은 경우에는 일반적인 JOIN보다 스칼라 서브 쿼리를 이용하는 것이 계산 속도가 유리하다.

-- salaries 테이블에서 직원 번호(emp_no)와 한 직원의 평균 급여(avg_salary)를 출력하는 스칼라 서브 쿼리
SELECT DISTINCT emp_no, (
SELECT AVG(salary) 
FROM salaries AS A
WHERE A.emp_no = B.emp_no
) AS avg_salary
FROM salaries AS B