[Oracle 기초] OUTER JOIN에서의 ON 과 WHERE의 차이

Posted by 열정보이
2019. 1. 6. 12:42 Oracle

안녕하세요~

오늘은 저번에 설명하지 못한 'OUTER JOIN에서의 ON 절과WHERE 절의 차이'에 대해 알아보겠습니다.
우리가 흔히 사용하는 INNER JOIN에서는ON 절과 WHERE 절은 같은 결과를 나타낸다고 했습니다.
하지만 ON과 WHERE는 다릅니다...!!
같다면 왜 나눠놨겠어요!!

그 둘의 차이는 바로 WHERE 절은 가져온 테이블에서 조건에 맞는 값을 가져오는 검색 조건으로 사용되고, ON 절은 JOIN을 할 때의 JOIN 조건이라는 점!!
바로 이것이 차이입니다!!

아 그렇구나!! 하고 와닿지 않습니다.. 저도 그랬습니다..
직접 쿼리를 보도록 하죠!!



위와 같은 테이블이 있다고 할 때, 두 테이블을 OUTER JOIN을 할 겁니다.

KEY는 PRODUCT_CODE로 잡을 것이고요.

직접 차이를 보도록 하겠습니다.


1
2
3
4
5
6
7
SELECT 
    B.BUY_TIME, B.USER_CODE, B.COUNT, B.PRICE, 
    P.PRODUCT_CODE, P.PRODUCT_NAME, P.PRICE
FROM BUY_HIS B , PRODUCT_TABLE P
WHERE B.PRODUCT_CODE(+= P.PRODUCT_CODE
AND P.PRICE <= 5000
ORDER BY B.HIS_NUMBER;
cs


다음과 같은 쿼리가 있다고 하겠습니다.

두 테이블을 RIGHT OUTER JOIN 하고 AND로 조건을 하나 더 주었습니다.

바로 P.PRICE <= 5000 미만이라는 것이죠.

결과는 어떨까요?



결과를 보아하니, RIGHT OUTER JOIN 후 P.PRICE 가 5000미만인 값만 가져온 것 같습니다.

실행계획을 보고 정확히 판단하도록 하죠.

실행계획 같은 경우 여러 가지 방법이 있는데 쿼리가 시작 전에 EXPLAIN PLAN FOR을 붙여주고, 실행시킨 다음
SELECT * FROM TABLE(dbms_xplan.display)를 실행시켜주면 됩니다.


1
2
3
4
5
6
7
8
9
10
EXPLAIN PLAN FOR
SELECT 
    B.BUY_TIME, B.USER_CODE, B.COUNT, B.PRICE, 
    P.PRODUCT_CODE, P.PRODUCT_NAME, P.PRICE
FROM BUY_HIS B , PRODUCT_TABLE P
WHERE B.PRODUCT_CODE(+= P.PRODUCT_CODE
AND P.PRICE <= 5000
ORDER BY B.HIS_NUMBER;
 
SELECT * FROM TABLE(dbms_xplan.display);
cs


이런 식으로 말이죠. 

아무튼 결과를 보니 다음과 같습니다.



실행계획은 '안에서부터 밖'으로 읽습니다. 가장 왼쪽에 ID라고 해서 숫자가 보이시죠?

그렇다면 읽는 순서는 다음과 같습니다. 3 -> 4 -> 2 -> 1 -> 0입니다.

먼저 3,4에서 TABLE ACCESS가 일어나네요. 근데 ID에 별표가 쳐져 있는 으로 로우들이 있죠? 이런 건 뭔가 작업이 일어났다는 겁니다.

바로 아래 17행을 보면 PRODUCT_TABLE을 ACCESS 할 때, FILTER 작업을 거쳤네요.

바로 P.PRICE <= 5000미만인 걸로 말입니다.


즉, 위 쿼리는 JOIN을 하기 전에 두 테이블을 가져올 텐데, 가져올 때 WHERE 절이 먼저 실행되어 P.PRICE 값이 5000미만인 값만 가져온 상태에서 OUTER JOIN이 발생한 겁니다.

PRODUCT_TABLE에 PRICE 값이 5000미만인 값뿐이기 때문에 아무리 RIGHT OUTER JOIN을 해도 5000 이상의 값이 나올 수가 없는 것이죠.



여기까지 이해하셨나요?


그렇다면 바로 ON 절의 쿼리로 가보겠습니다.


1
2
3
4
5
6
7
SELECT 
    B.BUY_TIME, B.USER_CODE, B.COUNT, B.PRICE, 
    P.PRODUCT_CODE, P.PRODUCT_NAME, P.PRICE
FROM BUY_HIS B RIGHT OUTER JOIN PRODUCT_TABLE P
ON B.PRODUCT_CODE = P.PRODUCT_CODE
AND P.PRICE <= 5000
ORDER BY B.HIS_NUMBER;
cs


WHERE를 사용하지 않고, ON을 사용하여 P.PRICE<= 5000 인 조건을 주었죠.

결과를 볼까요?



놀라운 현상이 발생했습니다. 분명 P.PRICE <= 5000을 주었는데도 불구하고 P.PRICE에 5000 이상의 값들이 보입니다...

이게 바로 ON과 WHERE의 차이입니다.


아까 말씀드렸듯이 WHERE는 검색 조건입니다. 하지만 ON 절은 JOIN 조건이죠.

위의 쿼리는 'P.PRICE <= 5000 미만인 값들에 한해서 조인을 한다. 나머지는? OUTER JOIN을 한다.'로 해석이 되는 겁니다. 잘 이해가 안될 수 있으니 P.PRICE <= 5000을 지우고 다시 결과를 보도록 하겠습니다.



해당 조인 조건을 지우자마자, PRODUCT_CODE 값이 P005 인 로우가 조인되어 나타났습니다.


왜 아까는 나타나지 않았을까요? 바로 '조인 조건이 P.PRICE <= 5000 미만이었는데, P005의 PRICE 값은 13,000원이기 때문에 조인 조건에 성립되지 않아, 조인이 발생하지 않았던 것'이죠.


실행계획을 볼까요?



HASH JOIN OUTER가 발생할 때, RIGHT OUTER JOIN으로 ACCESS 되면서 FILTER가 이루어지네요. 

이때 P.PRICE <= 5000으로 발생하는 걸 보면, 'P.PRICE 가 5000 미만인 값에 RIGHT OUTER JOIN을 실행한다. '라고 

해석하면 되겠습니다.


이제 ON 절과 WHERE 절의 차이를 이해하셨나요?

저도 이 차이를 정확히 이해하지 못해, 구루비넷에 물어봤었습니다. 아마 잘 찾아보신다면 위에 똑같은 사진을 올린 열정 가이란 놈이 있을 겁니다..... ㅋㅋㅋ 이런 커뮤니티를 이용하는 것도 좋은 방법이라고 생각해요. 친절하게 답변해주시는 분들도 많으시거든요.


아무튼 ON 절은 조인 조건을 줄 때 사용하고, WHERE 절은 검색 조건을 줄 때 사용한다는 점!!

기억해두세요!!