본문 바로가기

카테고리 없음

ORACLE <> JOIN v1.0

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 건 만큼 증가하게 되었다.