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 |