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
'지극히 개인적인 공부 노트 > 데이터베이스(Database)' 카테고리의 다른 글
[SQL] JOIN 활용하기 (0) | 2021.09.26 |
---|---|
[SQL] 일반 집합 연산(feat. UNION, INTERSECT, EXCEPT) (0) | 2021.09.25 |
[SQL] 기초적인 SQL 내장 함수(feat. COUNT, SUM, AVG, MAX, MIN, GROUP BY) (0) | 2021.09.14 |
[SQL] 대표적인 DML 명령어(feat. LIKE, ORDER BY, INSERT, UPDATE, DELETE) (0) | 2021.09.14 |
[SQL] 테이블에서 데이터 검색 및 조회하기(feat. 테이블, 컬럼, 레코드) (0) | 2021.09.14 |