SELECT
문SELECT (SELECT ... FROM ...) -- 스칼라 서브쿼리
FROM (SELECT ... FROM ...) -- 인라인 뷰
WHERE 컬럼명 IN (SELECT ... FROM ...) -- 중첩 서브쿼리
SELECT
절에 있는 또 다른 SELECT
절각 부서에서 가장 높은 연봉을 받는 직원들의 연봉을 각 직원의 정보와 함께 조회하기 위해 아래의 SQL문을 실행한다고 하자.
SELECT
employee_id,
name,
salary,
(SELECT MAX(salary) FROM employees GROUP BY department_id) AS max_salary_in_dept
FROM
employees;
GROUP BY department_id
때문에 스칼라 서브쿼리는 각 부서별 MAX(salary) 값을 반환한다. 부서가 여러 개 이므로 MAX(salary)가 여러 개가 된다.즉, 이 쿼리의 결과를 예상해본다면 다음과 같다.
employee_id | name | salary | max_salary_in_dept |
---|---|---|---|
1000 | Ariel | 3000 | 5000, 3500 ... ➡️ 부서별 MAX(salary) 값이 전부 들어가게 된다. |
SELECT
e.employee_id,
e.name,
e.department_id,
e.salary,
d.max_salary
FROM
employees e
INNER JOIN (
SELECT department_id, MAX(salary) AS max_salary
FROM employees
GROUP BY department_id
) d ON e.department_id = d.department_id
WHERE e.salary = d.max_salary;
FROM
절에 있는 또 다른 SELECT
절FROM
절 내부에서 일시적으로 뷰를 생성한다.SELECT 학생A.학번, 학생A.이름
FROM (SELECT *
FROM 학생
WHERE 성별 = '남') 학생A;
WHERE
절에 있는 또 다른 SELECT
절SELECT *
FROM 학생
WHERE 학번 = (SELECT MAX(학번)
FROM 학생)
비상관 서브쿼리에서 실행 순서
서브쿼리 실행 ➡️ 메인쿼리 실행 ➡️ 결과 출력
SELECT *
FROM 학생
WHERE 학번 IN (SELECT 학번
FROM 학생
WEHRE 성별 = '남')
성별 = '남'
조건으로 학생
테이블에서 데이터를 필터링해 가져온 뒤학생
테이블로 전달하여 최종 데이터를 출력한다.상관 서브쿼리에서 실행 순서
메인쿼리 실행 ➡️ 서브쿼리 실행 ➡️ 메인쿼리 실행 ➡️ 결과 출력
SELECT *
FROM 학생
WHERE 학번 IN (SELECT 학번
FROM 지도교수
WEHRE 성별 = 지도교수.학번 = 학생.학번)
학생
테이블의 학번 결과를 서브쿼리로 전달한다.지도교수.학번 = 학생.학번
으로 학생
테이블과 지도교수
테이블의 학번을 비교한다.학생
테이블과 지도교수
테이블의 학번이 같을 때, 서브쿼리의 결과로 도출된다.cf) 2-1, 2-2 과정에서 'SQL 재작성'이 작동할 수 있다.
- DB 버전 및 옵티마이저에 따라,
- 서브쿼리가 제거되고, 하나의 메인쿼리로 통합되는 "뷰 병합 (view merging)" 발생 가능
- 이 과정을 "SQL 재작성 (rewrite)" 라고 한다.
WHERE
절에서 연산자(<, >, = 등)을 사용해 서브쿼리를 연결한다.WHERE 학번 = (SELECT MAX(학번)
FROM 학생)
WHERE
절에서 IN
구문을 사용해 서브쿼리를 연결한다.WHERE 학번 IN (SELECT MAX(학번)
FROM 학생
GROUP BY 전공코드)
WHERE
절에서 IN
구문을 사용해 서브쿼리를 연결한다.WHERE (이름, 전공코드) IN (SELECT 이름, 전공코드
FROM 학생
WHERE 이름 LIKE '김%')
📌 Source
💡 질문과 피드백은 댓글에 남겨주시기 바랍니다.
❤️ 도움이 되셨다면 공감 부탁드립니다.