서브쿼리에 대하여

Hoo-Sung.Lee·2024년 9월 10일
0

Database

목록 보기
13/18

서브쿼리(subquery)란?

SELECT  (SELECT ... FROM ...)
	FROM  (SELECT ... FROM ...)
WHERE 칼럼명 IN (SELECT ... FROM ...)

서브쿼리는 쿼리 안의 보조쿼리를 가리키는 용어다. 가장 바깥쪽의 SELECT문인 메인쿼리를 기준으로 내부에 SELECT 문을 추가로 작성해서 서브쿼리를 만든다.
메인쿼리 안에 위치한 SELECT문은 어느 위치에 작성되었는지에 따라 부르는 용어가 달라진다.
서브쿼리의 각 위치별로 자세히 살펴보도록 하자.

1. SELECT 절에 위치한 경우

주로 메인 쿼리의 SELECT절 내부에 하나의 숫자나, 문자 기호 등을 출력하는 SELECT문으로 스칼라 서브쿼리(scalar subquery)라고 한다.

SELECT 이름,
	(SELECT COUNT(*)
    	FROM 학생 AS 학생2
       WHERE 학생2.이름 = 학생1.이름) 카운트
    FROM 학생 AS 학생1;

보통 스킬라 서브쿼리는 출력되는 데이터 건수가 1건이어야 하므로 집계함수(max,min, avg, sum,count 등)가 자주 쓰인다.

2. FROM 절에 위치한 경우

메인 쿼리의 FROM 절에 있는 또 다른 SELECT 절을 인라인 뷰라고 한다.

  • 인라인 뷰의 결과는 내부적으로 메모리 또는 디스크에 임시 테이블을 생성하여 활용된다. 그러므로 주의가 필요하다.!!
SELECT 학생2.학번, 학생2.이름
	FROM (SELECT *
    		FROM 학생
            WHERE 성별 = '남') 학생2;

3. WHERE 절에 위치한 경우: 중첩 서브쿼리

메인쿼리의 WHERE 절에 있는 또 다른 SELECT 절을 중첩 서브쿼리라고 한다.
WHERE 절에서 단순한 값을 비교 연산하는 대신, 서브쿼리를 추가하여 비교 연산하기 위해 중첩 서브쿼리를 사용한다.

SELECT *
	FROM 학생
    WHERE 학번 = (SELECT MAX(학번)
    				FROM 학생)

이처럼 WHERE 절에서 중첩 서브쿼리와 비교할 때는 아래의 1번과 같은 연산자와, 2번과 같은 문을 많이 사용한다.

  1. 비교 연산자 (=,<,>,<=, >=, < >, !=)
  2. IN, EXISTS, NOT IN, NOT EXIST 문

메인쿼리와의 관계성에 따른 분류

분류 기준: 서브 쿼리가 독자적으로 실행 할 수 있는지

비상관 서브쿼리

비상관 쿼리는 메인쿼리와 서브 쿼리 간에 관계성이 없음을 의미한다.
서브쿼리가 독자적으로 실행된 뒤 메인쿼리에게 그 결과를 던져주는 형태이다.

실행 순서: 서브쿼리 실행 -> 메인 쿼리 순으로 실행한다.

오해했던 부분: 서브 쿼리가 실행을 마치고 메인 쿼리에게 그 결과를 준다는 둘 간의 상관이 있는거 아닌가?? 라는 생각 때문에 dependent subquery이지 않을까라는 잘못된 생각을 했었다. 하지만 비상관 서브쿼리와 상관 서브쿼리의 분류 기준은 "서브 쿼리가 독자적으로 실행할 수 있는지"이다. 명심하자.

SELECT *
	FROM 학생
    WHERE 학번 IN (SELECT 학번
    				FROM 학생
                    WHERE 성별 = '남')

위의 예제는 성별 = '남' 조건으로 학생 테이블에서 데이터를 가져온 뒤 그 결과를 메인쿼리의 학생 테이블로 전달하여 최종 결과를 출력한다. 이 때, 옵티마이저에 따라 서브 쿼리가 제거되고 하나의 메인 쿼리로 통합되는 뷰 병합이 작동될 수도 있다.

상관 서브쿼리

서브 쿼리가 메인 쿼리와 관계성이 있어, 독자적으로 실행될 수 없는 경우를 말한다.
서브쿼리가 수행되려면 메인쿼리의 값을 받아야 하므로 서브쿼리와 메인쿼리는 서로 끈끈한 관계를 유지한다.

이러한 상관 서브쿼리가 발생하는 상황

  1. 스칼라 서브쿼리(SELECT 절)
  2. 중첩 서브쿼리(WHERE 절)
SELECT *
	FROM 학생
 	WHERE 학번 IN (SELECT 학번
  				FROM 지도교수
                  WHERE 지도교수.학번 = 학생.학번)

위의 쿼리는 지도교수 테이블의 학번과 학생 테이블의 학번이 동일할 경우에만 결과를 출력하는 조금 말도 안되는 예제이긴 하다. 상관 서브쿼리를 이해하는 용도로만 분석해보기로 하자.

실행순서
1. 메인 쿼리 실행(학생.학번 데이터 가져오기)
2. 서브 쿼리 실행(지도교수 학번 = 학생.학번)
3. 다시 메인 쿼리를 실행한 뒤 결과 출력(SELECT * FROM 학생)

서브쿼리의 "지도교수.학번 = 학생.학번" 부분을 보면, 독자적으로 실행할 수 없고 메인 쿼리로부터 학생.학번 데이터를 공급받아야 서브 쿼리를 실행할 수 있다. 이러한 관계일 때, 서브쿼리를 상관 서브쿼리라고 한다.

물론, 이때도 DB 버전 및 옵티마이저에 따라 서브쿼리가 제거되고 하나의 메인 쿼리로 통합되는 뷰 병합으로 작동할 수 있다.

profile
Working towards becoming Backend-Developer

0개의 댓글