ORACLE <> JOIN
from
1.
ORACLE <> JOIN
ORACLE 에는 JOIN 연산자로 쓰이는 많은 표현이 있다. 개중에는 <> 도 있다. 하지만 이 연산자의 결과물을 보면 정상적인
조인이 아니란 걸 알 수 있다. 다시 말하자면 사용할 일이 있는가 싶다. 쉽게 생각하면 같지 않은걸 뽑기위해 사용했다라고 말할 수 있겠지만 이 결과는 생각한 것보다 훨씬 많다.
2.
<> 연산의
의미
이는 말그대로 같지 않다란 뜻이다. 서로 비교를 했고 그에
대한 결과를 냈다는 것은 비교값에 NULL 이 사용되지 않았다는 것을 의미한다. 또한 NL LOOP JOIN 을 생각했을 때 일반적으로 하나의 ROW 에 대해 INNER TABLE 과의 연결을 시도했을 때 연결이
실패 ( 값이 다른 경우… 여기서는 실패한 연결이 운반단위로
이동한다.) 한 결과가 훨씬 많을 것이다.
3.
<> JOIN 예제
여기서는 예제로 HR.EMPLOYEES 와 HR.JOBS 를 사용했다.
SQL> select count(*) from employees;
COUNT(*)
----------
107
SQL> select count(*) from jobs;
COUNT(*)
----------
19
각 테이블에 대해 그 건수는 107 과 19 건이다. 연결고리로 사용할 것은 JOB_ID 이며 두 테이블 다 NOT NULL 조건을 가지고 있다.
SQL> select 107*19 from dual;
107*19
----------
2033
SQL> select count(*) from
2 (select /*+ no_unnest */
a.*,b.*
3 from employees a, jobs b);
COUNT(*)
----------
2033
두 테이블에 대해 카티션 곱을 만들면 2033 건이 나온다.
SQL> select count(*) from
2 (select a.*,b.* from
3 employees a, jobs b
4 where a.job_id = b.job_id);
COUNT(*)
----------
107
정상적으로 조인을 한 결과는 107 건이 나온다.
SQL> ed
Wrote file afiedt.buf
1 select count(*) from
2 (select a.*,b.* from
3 employees a, jobs b
4*
where a.job_id <> b.job_id)
SQL> /
COUNT(*)
----------
1926
이제 <> 를 사용해 JOIN 을 시도해 보았다.
결과 건수로 1926 이 나왔다.
이는 조인에 성공한 결과 107 건을 카티션 곱 2033 에서 뺀 값과 동일하다.
SQL> select 1926+107 from dual;
1926+107
----------
2033
SQL> create table employees1
2 as select * from employees;
Table created.
employees 테이블을 복제해 employees1 을 생성하였다.
SQL> select
constraint_name,table_name,column_name
2 from user_cons_columns
3 where table_name =
'EMPLOYEES1';
CONSTRAINT_NAME TABLE_NAME COLUMN_NAME
-------------------- ----------
--------------------
SYS_C003313 EMPLOYEES1 HIRE_DATE
SYS_C003312 EMPLOYEES1 EMAIL
SYS_C003314 EMPLOYEES1 JOB_ID
SYS_C003311 EMPLOYEES1 LAST_NAME
SQL> alter table employees1
2 drop constraint sys_c003314;
Table altered.
조인고리 (job_id) 에 걸려있는 not null 을 삭제하였다.
SQL> insert into
employees1(last_name,email,hire_date)
2 values('lll','sss',sysdate);
1 row created.
SQL> commit;
Commit complete.
조인고리에 대해 null 로 두고 아까 수행했던 쿼리를 trace 해 보았다.
select count(*) from
(select a.*,b.* from
employees1 a, jobs b
where a.job_id <> b.job_id)
/
Rows Row Source Operation
------- ---------------------------------------------------
1
SORT AGGREGATE (cr=339 pr=0 pw=0 time=5052 us)
1926
NESTED LOOPS (cr=339 pr=0 pw=0
time=37166 us)
108
TABLE ACCESS FULL EMPLOYEES1 (cr=15 pr=0 pw=0 time=679 us)
1926
INDEX FAST FULL SCAN JOB_ID_PK (cr=324 pr=0 pw=0 time=11566 us)(object
id 9970)
결과를 보면 단순히 조인에 성공한 건수만 제외되는 것이 아니라 비교할 수 없는 결과 (null) 에 대해서도 제외되었음을 알 수 있다.
이번에는 연결고리에 값은 있지만 조인이 실패할 값을 입력했다.
(위에 추가했었던 row 는 삭제했다.)
SQL> insert into
employees1(last_name,email,hire_date,job_id)
2
values('111','111',sysdate,'111');
1 row created.
SQL> commit;
Commit complete.
select count(*) from
(select a.*,b.* from
employees1 a, jobs b
where a.job_id <> b.job_id)
/
Rows Row
Source Operation
-------
---------------------------------------------------
1
SORT AGGREGATE (cr=339 pr=0 pw=0 time=4369 us)
1945
NESTED LOOPS (cr=339 pr=0 pw=0
time=21724 us)
108
TABLE ACCESS FULL EMPLOYEES1 (cr=15 pr=0 pw=0 time=604 us)
1945
INDEX FAST FULL SCAN JOB_ID_PK (cr=324 pr=0 pw=0 time=9402 us)(object id
9970)
결과를 보면 1926 에서
19 건이 증가한 1945 건이란 값이 나왔다. 조인고리에
값이 다 있다는 것은 상호 비교가 가능하다는 것이고 이에 따른 결과는 조인에 성공/실패 가 나온다는
것이다. 새로 추가한 row 는 조인에 실패할 값이었고 그로
인해 jobs 의 rows 수 19 건 만큼 증가하게 되었다.