MySQL에서 다른 서브쿼리 안에 서브쿼리를 중첩하는 방법
하나의 서브쿼리가 다른 서브쿼리 내부에 포함된 형태를 중첩 서브쿼리(nested subquery)라고 합니다. SQL에서는 쿼리 안에 쿼리를 여러 겹으로 작성할 수 있으며, 실행 시에는 가장 안쪽의 서브쿼리부터 순서대로 처리되고 그 결과가 바깥쪽 쿼리의 조건 값으로 전달됩니다.
이해를 돕기 위해 아래 세 개의 샘플 테이블을 사용해 중첩 서브쿼리를 단계별로 살펴보겠습니다.
예제 테이블
① Cars 테이블 – 차량 목록 및 가격 정보
mysql> Select * from Cars; +------+--------------+---------+ | ID | Name | Price | +------+--------------+---------+ | 1 | Nexa | 750000 | | 2 | Maruti Swift | 450000 | | 3 | BMW | 4450000 | | 4 | VOLVO | 2250000 | | 5 | Alto | 250000 | | 6 | Skoda | 1250000 | | 7 | Toyota | 2400000 | | 8 | Ford | 1100000 | +------+--------------+---------+ 8 rows in set (0.02 sec)
② Customers 테이블 – 고객 정보
mysql> Select * from Customers; +-------------+----------+ | Customer_Id | Name | +-------------+----------+ | 1 | Rahul | | 2 | Yashpal | | 3 | Gaurav | | 4 | Virender | +-------------+----------+ 4 rows in set (0.00 sec)
③ Reservations 테이블 – 차량 예약 기록
mysql> Select * from Reservations; +------+-------------+------------+ | ID | Customer_id | Day | +------+-------------+------------+ | 1 | 1 | 2017-12-30 | | 2 | 2 | 2017-12-28 | | 3 | 2 | 2017-12-29 | | 4 | 1 | 2017-12-25 | | 5 | 3 | 2017-12-26 | +------+-------------+------------+ 5 rows in set (0.00 sec)
중첩 서브쿼리 예제
아래는 서브쿼리가 두 겹으로 중첩된 실제 쿼리 예시입니다. 'BMW' 차량과 관련된 예약 정보를 통해 해당 고객의 정보를 조회하는 구조로 작성되었습니다.
mysql> Select * from Customers where customer_id IN (Select Customer_id from reservations where id = (Select id from cars WHERE name = 'BMW')); +-------------+---------+ | Customer_Id | Name | +-------------+---------+ | 2 | Yashpal | +-------------+---------+ 1 row in set (0.00 sec)
쿼리의 동작 원리
중첩 서브쿼리는 안쪽에서 바깥쪽 방향으로 실행됩니다. 위 쿼리의 각 계층은 다음과 같은 역할을 담당합니다.
- 가장 안쪽 서브쿼리 –
Select id from cars WHERE name = 'BMW': Cars 테이블에서 이름이 'BMW'인 차량의 ID를 찾습니다. - 중간 서브쿼리 –
Select Customer_id from reservations where id = ...: 앞 단계에서 구한 차량 ID와 일치하는 예약 건의 고객 ID(Customer_id)를 조회합니다. - 가장 바깥쪽 메인 쿼리 –
Select * from Customers where customer_id IN (...): 조회된 고객 ID에 해당하는 고객의 상세 정보를 최종 결과로 반환합니다.
중첩 서브쿼리 작성 시 유의 사항
- 안쪽 서브쿼리가 여러 행을 반환할 가능성이 있다면
=대신IN,ANY,ALL같은 연산자를 사용해야 오류를 피할 수 있습니다. - 결과가 반드시 하나의 값이라면
=연산자를 사용하는 것이 적절합니다. - 중첩 깊이가 깊어질수록 가독성과 성능이 저하될 수 있으므로, 상황에 따라 JOIN 방식으로 변환하는 것이 더 효율적일 수 있습니다.