서브쿼리를 INNER JOIN으로 변환하기
SQL에서 서브쿼리(subquery)는 종종 INNER JOIN으로 변환하여 더 명확하고 성능이 좋은 쿼리를 작성할 수 있습니다. 이해를 돕기 위해 다음 두 개의 테이블 데이터를 사용하겠습니다.
예제 테이블
먼저 customers(고객) 테이블입니다.
mysql> Select * from customers; +-------------+----------+ | Customer_Id | Name | +-------------+----------+ | 1 | Rahul | | 2 | Yashpal | | 3 | Gaurav | | 4 | Virender | +-------------+----------+ 4 rows in set (0.00 sec)
다음은 reserve(예약) 테이블입니다.
mysql> Select * from reserve; +------+------------+ | ID | Day | +------+------------+ | 1 | 2017-12-30 | | 2 | 2017-12-28 | | 2 | 2017-12-25 | | 1 | 2017-12-24 | | 3 | 2017-12-26 | +------+------------+ 5 rows in set (0.00 sec)
서브쿼리 예제
아래는 차량을 예약한 모든 고객의 이름을 찾는 서브쿼리입니다.
mysql> Select Name from customers WHERE customer_id IN (Select id from reserve); +----------+ | Name | +----------+ | Rahul | | Yashpal | | Gaurav | +----------+ 3 rows in set (0.00 sec)
INNER JOIN으로 변환하는 단계
위 서브쿼리는 다음 단계를 통해 INNER JOIN으로 변환할 수 있습니다.
- 서브쿼리에 언급된 'Reserve' 테이블을 FROM 절로 이동합니다.
- WHERE 절에서 customer_id 컬럼과 서브쿼리가 반환한 id 값을 비교하고 있으므로, 이를 두 테이블의 id 컬럼 간 직접 비교로 바꿉니다.
그 결과 두 컬럼 간의 명시적인 직접 비교 조건으로 변환됩니다.
mysql> SELECT Name from customers, reserve WHERE customer_id = id; +----------+ | Name | +----------+ | Rahul | | Yashpal | | Yashpal | | Rahul | | Gaurav | +----------+ 5 rows in set (0.00 sec)
DISTINCT로 중복 제거
위 결과에는 중복된 이름이 포함되어 있어 서브쿼리의 결과와 정확히 일치하지 않습니다. 한 고객이 여러 번 예약하면 예약 건수만큼 행이 생성되기 때문입니다. 동일한 결과를 얻으려면 DISTINCT 키워드를 사용하여 중복을 제거하면 됩니다.
mysql> SELECT DISTINCT name from customers, reserve WHERE customer_id = id; +----------+ | Name | +----------+ | Rahul | | Yashpal | | Gaurav | +----------+ 3 rows in set (0.03 sec)
이처럼 IN 연산자를 사용하는 서브쿼리는 FROM 절에 관련 테이블을 추가하고 조인 조건을 명시하는 것만으로 간단하게 INNER JOIN 형태로 변환할 수 있으며, DISTINCT를 활용하면 원래 결과와 동일하게 유지할 수 있습니다.