✅ 아무리 옵티마이저가 JOIN 순서·실행 순서를 바꿔도 결과는 절대 달라지지 않는다.
이건 표준 SQL의 보장 사항이다.
🎯 왜 절대 결과가 달라지지 않을까?
이유는 간단함:
SQL은 선언적 언어이기 때문.
즉,
“어떻게 실행할지” 가 아니라
“어떤 결과가 나와야 하는지” 를 명시하는 언어.
따라서 SQL 엔진은 논리적으로 같은 결과를 만들 수 있다면
아무리 실행순서를 바꿔도 된다.
🧠 순서가 바뀔 수 있지만 의미는 동일하다
SQL의 논리적 순서(개발자가 읽는 순서):
FROM
WHERE
GROUP BY
HAVING
SELECT
ORDER BY
하지만 실제 옵티마이저는 이렇게 안 한다.
예를 들어:
WHERE 조건을 먼저 적용할 수도 있고
JOIN 순서를 바꿀 수도 있고
서브쿼리를 먼저 실행할 수도 있고
인덱스를 먼저 읽고 필요한 것만 JOIN할 수도 있다
하지만 최종적으로는 “표현된 조건을 만족하는 row”만 출력해야 한다는 규칙은 바뀌지 않는다.
그래서 결과는 절대 변하지 않는다.
📌 상관 서브쿼리(Correlated Subquery)라면 더 안전하다
너가 사용한 쿼리 형태:
AND CMPP2.INSTCD = CMPP.INSTCD
이건 상관 서브쿼리이기 때문에
서브쿼리는 반드시 메인 CMPP의 값에 의존해서 실행된다.
이 때문에 더욱 결과가 변할 가능성이 없다.
📁 예시로 이해해보자
이 쿼리의 논리는:
메인 CMPP의 CMPYCD, INSTCD, APPYEAR 값과 정확히 같은 CMPP2 중에서 MIN(APPYEAR)을 구한다.
이 논리는 JOIN 순서가 어떻게 바뀌어도 달라지지 않는다.
잘못된 예측이 가능해보이는 경우
“옵티마이저가 CMPP2를 전체 스캔해서 먼저 모은 후 CMPP와 비교하면 어떻게 되지?”
→ 그래도 아래 조건이 있기 때문에 결과는 같음:
CMPP2.INSTCD = CMPP.INSTCD
CMPP2.APPYEAR = CMPP.APPYEAR
CMPP2.CMPYCD = CMPP.CMPYCD
즉 메인 CMPP에서 필터된 값만 비교 대상이 된다.
🚨 왜 실행 순서가 바뀌어도 결과는 같을 수밖에 없음?
SQL의 핵심 보장사항:
WHERE 절의 의미는 “이 조건을 만족하는 행만 결과에 포함하라”이지
“이 조건을 이 순서로 처리하라”는 뜻이 아니다.
즉:
어떤 테이블을 먼저 읽든
어떤 인덱스를 사용하든
어떤 조건을 먼저 적용하든
서브쿼리를 먼저 읽든
JOIN을 먼저 하든
조건의 논리적 의미만 지켜지면
결과는 100% 동일하다.
🎯 결론
✔ 옵티마이저가 실행순서를 바꿔도 결과는 절대 변하지 않는다
SQL의 선언적 특성 + WHERE 조건의 논리적 의미 때문.
✔ JOIN 순서가 바뀌어도 동등 조인(EQUI JOIN)은 결과가 항상 동일하게 나온다.
✔ 상관 서브쿼리라서 메인 row에 종속 → 더 안정적
메인 쿼리에서 CMPP와 CMPY가 JOIN되고 서브쿼리에서 CMPP2와 CMPP가 JOIN되는데 서브쿼리에서 JOIN당시의 CMPP2는 그냥 완전 처음 조회한 CMPP랑 JOIN이야 아니면 메인쿼리에서 좀 걸러진 기준인거야?
✅ 핵심 요약
서브쿼리는 메인 쿼리의 각 ROW마다 실행된다 (Scalar Subquery).
서브쿼리 안에서 사용하는 CMPP 값은
메인 쿼리에서 JOIN·WHERE까지 모두 적용된 결과의 CMPP 행이다.
즉, CMPP2는 “메인에서 필터링된 CMPP의 값”과 JOIN된다.
▶ 서브쿼리는 이렇게 실행됨
메인쿼리 B의 첫 번째 행(B.id = 10)을 기준으로 서브쿼리 실행:
SELECT ...
FROM C
WHERE C.id = 10 -- B.id(필터링된 값)
그리고 두 번째 행(B.id = 12)을 기준으로 다시 실행:
SELECT ...
FROM C
WHERE C.id = 12 -- B.id(필터링된 값)