dbms - join

DB/Common 2012. 7. 6. 11:28


JOIN의 경우 제정된 표준시기에 따라 2가지의 JOIN방식이있다.


<참고>예를들어 TBL_NEWSAWON, TBL_NEWDEPT 이름을가진 2가지 테이블을 JOIN할떄

 

1) SQL 1992 code - 92년도에 제정된 표준

 

SELECT *
FROM TBL_NEWSAWON, TBL_NEWDEPT;
  

2) SQL 1999 code

 

SELECT *
FROM TBL_NEWSAWON CROSS JOIN TBL_NEWDEPT;

 


1. INNER JOIN 
   - (92년도 표준으로 EQUI JOIN 이라고도한다.)
     일반적으로 INNER 를 쓰지 않아도 JOIN 으로 인식한다.
    
     INNER JOIN 은 JOIN 조건(ON 에서 조건지정)이 맞는 컬럼만 보여준다.
   
    
       

    SELECT *
    FROM TBL_NEWSAWON S , TBL_NEWDEPT D
    WHERE S.DEPTNO = D.DEPTNO;


    SELECT *
    FROM TBL_NEWSAWON S INNER JOIN TBL_NEWDEPT D
    ON S.DEPTNO = D.DEPTNO;

 

   다음에 나오는 OUTER JOIN과 결과물이 다를때가 있는데.

   바로밑에 OUTER JOIN을 설명할때 둘의 결과물을 비교해보겠다.

 

2. OUTER JOIN 
  

  - INNER 조인의 경우 조건에 맞지 않는 데이터는 나타나지 않는데. 특히 조인조건에 쓰이는 데이터값이
     NULL인 필드인 경우에 그렇다. 조건에 맞지 않는 데이터까지 추출하기위해서는 OUTER JOIN 을 쓴다.
    
     OUTER 또한 생략가능한데 OUTER 의 경우에는 LEFT,RIGHT,FULL 방식의 조인이있어서 INNER JOIN과
     구분할수 있다.


   

 

지금 설명한 INNER, OUTER 결과물을 비교해보자.

 다음과같은 2가지 테이블을 JOIN해보자
 

 

 

      <TBL_NEWDEPT; 부서테이블>

                                                                        

 

  <TBL_NEWSAWON; 사원정보테이블>

  

 

1) INNER JOIN 했을경우

   

    SELECT *
    FROM TBL_NEWSAWON S INNER JOIN TBL_NEWDEPT D
    ON S.DEPTNO = D.DEPTNO;

 

결과물을 보면 부서번혹 없는 '고두심' 필드가 안보임을 알수있다. 두 테이블을 연결시켜주는 PK인 DEPTNO comuml

인 부서번호가 NULL 인 '고두심'의 개인정보는 나타나지 않는다.

 

 

 

2) OUTER JOIN 했을경우

 

 

SELECT *
FROM TBL_NEWSAWON S LEFT OUTER JOIN TBL_NEWDEPT D     
ON S.DEPTNO=D.DEPTNO

위의 경우는 LEFT 옵션으로 JOIN 한 쿼리문인데 이경우에는 우린  '고두심' 필드를 볼수있다.

LEFT의 경우 WHERE 절에서 왼쪽의  사원정보테이블의 S.DEPTNO 값을 먼저 우선시하고 그에 맞추어  '= D.DEPTNO' 값을

처리해주므로 '고두심' 필드를 볼수있다.

 

 

 

그렇다면 RIGHT 옵션을 줄경우는??

 

 

SELECT *
FROM TBL_NEWSAWON S RIGHT OUTER JOIN TBL_NEWDEPT D     
ON S.DEPTNO=D.DEPTNO

 

밑의 결과를 보자.

 

 

 

밑에처럼 모두가 NULL인 필드가 보이는데 이것은 현재 '고두심'의 사원번호가없기 때문에

조회결과를 나타낼수 없기 떄문이다. LEFT 와 RIGHT 를 구분하는 방식을 이해하자.

 

 

 

<참고 - 두가지 표준방식에 존재하므로 다음은 같은 표현임을 이해하자.>


<SQL 1992 CODE >

 

SELECT *
FROM TBL_NEWSAWON S , TBL_NEWDEPT D;
WHERE S.DEPTNO=D.DEPTNO(+)  

위에서 (+)방향에 따른 주의 DEPT없으면 안나오거나 null 안나오거나한다.


 

<SQL 1999 CODE>

SELECT *
FROM TBL_NEWSAWON S LEFT OUTER JOIN TBL_NEWDEPT D     
WHERE S.DEPTNO=D.DEPTNO

 

 

위는 두가지는 같은 결과를 내는 쿼리문이다.

__________________________________________________________________

 

 

<SQL 1992 CODE >

 

SELECT *
FROM TBL_NEWSAWON S , TBL_NEWDEPT D;
WHERE S.DEPTNO(+)=D.DEPTNO 

의경우 99년도방식

 

<SQL 1999 CODE>


SELECT *
FROM TBL_NEWSAWON S RIGHT OUTER JOIN TBL_NEWDEPT D
ON S.DEPTNO=D.DEPTNO

 

위에 두가지 역시 같은 코드문이다.

_________________________________________________________________


단, FULL OUTER JOIN 의 경우는 99년도방식에만 존재

 

SELECT *
FROM TBL_NEWSAWON S FULL OUTER JOIN TBL_NEWDEPT D
ON S.DEPTNO=D.DEPTNO

 

NULl값을 가진 필드에 상관없이 모든 결과를 보여준다 즉 92년도방식으로따지자면

ON S.DEPTNO(+)=D.DEPTNO(+)  인데. 참고로 92년도방식으로는 이러한 구현이 불가능하다.

즉 위의 99년도 코드로만구현가능

 

 

 

3. NOT - EQUI JOIN (92년도방식)

 

ON이나 WHERE 절에서 '='  상태가아닌 특정상태의 조건절이 들어간구문이다.

 

 

 

SELECT *
FROM TBL_NEWSAWON S JOIN TBL_BONUS B
ON S.SAL BETWEEN B.LOWSAL AND B.HIGHSAL

 

 

 


4. SELF JOIN

 

아까 OUTER JOIN 에서 예를통해 사용해본 2개의 테이블을 생각해보자.

자신의 테이블간에 JOIN 을 해야할 경우가 있는데 이를 SELF JOIN이라한다.

 

그러나 밑에처럼 쿼리문을쓰면 에러가 난다.

 

SELECT *
FROM TBL_NEWSAWON, TBL_NEWSAWON; 구문은 에러다. 같은 테이블이름이 들어가버리므로.

 

따라서 엘리어싱으로 해결한다.


SELECT *
FROM TBL_NEWSAWON S1, TBL_NEWSAWON S2;

 

 

<SELF JOIN 할때 주의점 >

 - SELF JOIN 시에도 LEFT,RIGHT 구분을 해야한다.

 

2번에  나온 2개의 테이블을 이용해 예를 살펴보자


SELECT S1.JIK,S1.NAME, S2.JIK , S2.NAME
FROM TBL_NEWSAWON S1, TBL_NEWSAWON S2      

WHERE S1.MGR = S2.SANO;                    

 

 

 

위의 쿼리문을 보면 사장이 나타나지 않았다.

이것은 회장의 경우 MGR 값이 없기 때문이다.

(MGR 은 그 사원의 관리자(직속 직장상사)를 나타내므로 회장은 가장 높은 위치에 있으므로 값이 없을수 밖에 없다)

 

 
 .

LEFT OUTER JOIN을 씀으로서 해결가능하다.

 

SELECT S1.JIK,S1.NAME, S2.JIK , S2.NAME
FROM TBL_NEWSAWON S1 LEFT JOIN TBL_NEWSAWON S2       
ON S1.MGR = S2.SANO;   


 

 

5. CROSS JOIN 활용 - 두개의 테이블을 합처서 하나의 테이블처럼 생각해보는 테크닉


                 
예를통해 확인해보자.  

 

다음과같은 2개의 테이블이 있다고 하자.

TBL_NEWSAWON 테이블에는 사원의 이름(NAME),부서번호(DEPTNO), 판매량(SELL)을 표시해주고 있고
TBL_DPET 테이블은 원래 부서명이 있는 테이블이다. 두테이블은 현재 부모테이블인 TBL_DPET 와
자식테이블인 TBL_NEWSAWON 으로 나누어져 있음을 알수 있다.

 

 

 

 

이테이블에서 밑에와 같은 결과물을 내기위해서는

부서번호  판매량  판매점유율 
-------------------------------

-------------------------------

 

SELECT A.DEPTNO AS "부서당판매",
       A. "TOTALINDEPT"  AS "총판매",
       "TOTALINDEPT"/ "TOTAL" *100 || '%' AS "점유율"
FROM
(
SELECT DEPTNO, SUM(SELL) AS "TOTALINDEPT"
FROM TBL_NEWSAWON
GROUP BY DEPTNO
) A CROSS JOIN
(
SELECT SUM(SAL) AS "TOTAL"
FROM TBL_NEWSAWON
) B;


위에서처럼 INLINE 을 구성해서 A는 '부서당 판매수를 나타내는 테이블'
B는 '전체판매테이블'을 구성한다. 이를 CROSS함으로서 하나의 테이블처럼 생각할수 있고
이를 통해 우리가 원하는 데이터를 추출할수 있다.


<참고>

위에서 부서번호대신 부서이름을 나타내기위해서는 부서번호를 원래 부서명있는  
DEPT테이블과 JOIN해줘야한다 밑의 쿼리문을 참고하자.

또한 부서가 없는 사람이 있으므로 OUTER JOIN 을 해주어야하고 LEFT 로 방향도 조심.

- NVL2는 부서가 없는 사람의 카테고리를 만들어주기위해 사용했다.

 

SELECT NVL(A.DNAME,'부서없음') AS "부서명",
       A.DNAME AS "부서명",
       A. "TOTALDNAME"  AS "총판매",
       "TOTALDNAME"/ "TOTAL2" *100 || '%' AS "점유율"
FROM
(
SELECT B.DNAME, SUM(SELL) AS "TOTALDNAME"
FROM TBL_NEWSAWON A LEFT JOIN TBL_NEWDEPT B   
ON A.DEPTNO = B.DEPTNO
GROUP BY B.DNAME
) A CROSS JOIN
(
SELECT SUM(SAL) AS "TOTAL2"
FROM TBL_NEWSAWON
) B;


출처 - http://blog.daum.net/kwonmc/5918821





'DB > Common' 카테고리의 다른 글

SELECT문 순서와 처리순서  (0) 2012.08.29
데이터 입력과 db insert 사이에 버퍼링 방법  (0) 2012.07.13
sql - 서브(하위) 쿼리  (0) 2012.06.20
NoSQL 소개  (0) 2012.05.18
SQL 구문 기본 작성 가이드  (0) 2012.05.08
Posted by linuxism
,