서브 쿼리 조인
앞에서 NL 조인, 소트 머지 조인, 해시 조인 세 가지를 배웠는데 실무에 있다 보면 서브 쿼리 조인이라는 것이 있다 이 서브쿼리는 옵티마이저가 다양한 형태로 쿼리 변환을 시도하므로 서브 쿼리 조인을 이해하는 출발점은 쿼리 변환에서 찾아야 한다
서브 쿼리 변환이 필요한 이유
하나의 결과 집합을 얻기 위해 SQL 을 여러 가지 다른 형태로 표현할 수 있고 어떤 것을 선택하느냐에 따라 성능도 다를 수 있다 최근 옵티마이저는 사용자가 던져준 쿼리 안에서만 코스트를 책정할 뿐만 아니라 먼저 SQL 을 최적화에 유리한 형태로 변환하는 작업을 먼저 진행한다 쿼리 변환은 사용자로부터 받은 쿼리를 분석해서 동일한 결과 셋을 반환하면서 더 나은 성능이 나오기를 기대하는 형태로 재작성하는 것을 말합니다 이미 꽤 많은 쿼리 변환이 개발되었고 SQL 성능과 관련해 새로 개발되는 핵심 기능도 대부분 쿼리 변환 영역에 속하는데 이 영역은 그렇게 가볍게 볼 수 있는 영역이 아닙니다
서브 쿼리 종류
- 스칼라 서브 쿼리
1
2
3
4
5
SELECT T1.EMP_CD
,(SELECT MAX(JOIN_DT) FROM TABLE2 T2 )
FROM TABLE1 T1
스칼라 서브 쿼리는 한 레코드당 정확히 하나의 값을 변환하는 서브 쿼리인데 거의 대부분 select 문구에서 컬럼처럼 쓰이는 것이 대부분입니다
- 인라인 뷰
1
2
3
4
5
6
7
8
SELECT * FROM (
SELECT T1.EMP_CD
T1.TEL_NO
FROM TABLE1 T1
)
인라인 뷰는 FROM 절에 사용한 서브 쿼리를 말합니다
- 중첩된 서브 쿼리
1
2
3
4
5
SELECT *
FROM TABLE2 T2
WHERE T2.JOIN_DT = (SELECT MAX(JOIN_DT) FROM TABLE2 )
중첩된 서브 쿼리는 결과 집합을 한정하기 위해 where 절에 사용한 서브 쿼리를 말합니다
서브 쿼리 조인
메인 쿼리와 서브 쿼리 간에는 부모와 자식이라는 종속적이고 계층적인 관계가 존재한다 서브 쿼리는 메인 쿼리에 종속되므로 단독으로 실행할 수 없다 메인 쿼리 건수만큼 값을 받아 반복적으로 필터링하는 방식으로 실행해야 한다
이야기를 풀어서 써보자
부모 자식 관계 서브 쿼리는 메인 쿼리의 자식 역할을 하며 메인 쿼리는 서브 쿼리의 부모 역할을 하는 것입니다 서브 쿼리는 메인 쿼리의 자식 역할을 하는 것입니다 자식 쿼리의 역할은 부모 쿼리의 결과를 필터링하는 역할을 담당합니다
단독 실행 불가 서브 쿼리는 단독으로 실행할 수 없습니다 서브 쿼리가 부모 쿼리 안에 들어가 있어야 진정한 의미로 서브 쿼리의 역할을 하는 것입니다
반복적인 필터링 서브 쿼리는 메인 쿼리의 각 행(row)에 대해 실행되어야 할 때가 많습니다. 메인 쿼리에서 처리하는 각 데이터가 있을 때마다, 서브 쿼리가 해당 데이터에 대해 값을 계산하거나, 조건을 비교하여 필터링하는 방식으로 실행됩니다.
1
2
3
4
5
SELECT emp_name, salary
FROM employees
WHERE salary > (SELECT AVG(salary) FROM employees);
이때 부모 쿼리는
1
2
3
4
5
SELECT emp_name, salary
FROM employees
WHERE salary
자식 쿼리는
1
2
3
SELECT AVG(salary) FROM employees
이 서브 쿼리는 메인 쿼리에서 각 직원의 급여(salary)가 전체 직원의 평균 급여보다 큰지 확인하는 데 사용됩니다. 서브 쿼리는 메인 쿼리의 조건을 결정하는 데 중요한 역할을 합니다.