조인(JOIN)은 두 테이블에서 조인 조건이 맞는 행끼리 이어 한 줄로 만듭니다. 외부 조인(OUTER JOIN)은 짝이 없는 행도 남기고 빈칸을 NULL로 채웁니다.
EMP 테이블에는 사원의 부서 번호(DEPTNO)만 있고, 부서 이름(DNAME)은 DEPT 테이블에 있습니다. 사원 이름과 부서 이름을 한 줄에 보려면 두 테이블을 이어야 합니다. 이때 짝이 없는 행을 버리느냐 남기느냐에 따라 내부 조인(INNER JOIN)과 외부 조인으로 나뉩니다.
1조인 조건과 등가 조인
E·D는 FROM 절에서 EMP·DEPT에 붙인 테이블 별칭입니다.
E.DEPTNO = D.DEPTNO처럼 행을 잇는 조건이 조인 조건이고, 짝은 여럿일 수 있습니다.
DEPT의 20번 개발 행은 사원 셋과 짝지어져 결과에 세 번 나옵니다.
이처럼 =로 같은 값끼리 잇는 조인을 등가 조인(EQUI JOIN)이라 합니다.
별칭을 붙인 쿼리 안에서는 EMP.ENAME이 아니라 E.ENAME으로 씁니다(어기면 ORA-00904).
두 테이블에 다 있는 DEPTNO는 E.DEPTNO처럼 어느 쪽 열인지 밝힙니다(빠뜨리면 ORA-00918).
Oracle은 테이블 별칭 앞에 AS를 받지 않아 FROM EMP AS E는 오류입니다.
2내부 조인과 짝 없는 행
정하늘(1005)은 DEPTNO가 NULL이라 어떤 값과 견줘도 알 수 없음이 되어 짝이 없습니다. 40번 인사 부서는 사원이 없습니다. 둘은 잘못된 데이터가 아니라 짝이 없을 뿐이지만, 짝이 있는 행만 남기는 내부 조인(INNER JOIN)에서는 빠집니다.
INNER JOIN … ON처럼 FROM 절에 조인 키워드를 쓰는 꼴이 표준 조인(STANDARD JOIN)입니다.
테이블을 쉼표로 늘어놓고 조인 조건을 WHERE에 써도 내부 조인이 됩니다.
INNER는 생략할 수 있어, JOIN만 쓰면 내부 조인입니다.
3외부 조인
외부 조인이 짝 없는 행을 남기는 쪽은 테이블을 JOIN의 어느 쪽에 썼느냐로 정합니다.
LEFT는 왼쪽, RIGHT는 오른쪽, FULL은 양쪽 테이블의 행을 모두 남깁니다.
그래서 DEPT D RIGHT OUTER JOIN EMP E는 EMP E LEFT OUTER JOIN DEPT D와 같은 6행입니다.
그림 결과 표 끝 칸의 ✓·✕가 짝 없던 두 줄이 남는지 보입니다.
| 조인 | 정하늘 줄 | 40번 부서 줄 | 행 수 |
|---|---|---|---|
| INNER JOIN | ✕ | ✕ | 5 |
| LEFT OUTER JOIN | ✓ | ✕ | 6 |
| RIGHT OUTER JOIN | ✕ | ✓ | 6 |
| FULL OUTER JOIN | ✓ | ✓ | 7 |
행 수는 짝이 있는 5행에 남긴 짝 없는 행을 더합니다.
OUTER도 생략할 수 있어 LEFT JOIN은 LEFT OUTER JOIN과 같습니다.
4Oracle의 (+) 표기
Oracle은 쉼표 조인의 WHERE 조건에 (+)를 붙여 외부 조인을 씁니다.
(+)는 NULL로 채워지는 쪽 테이블의 열에 붙이고, (+)가 없는 쪽 테이블의 행이 모두 남습니다.
완전 외부 조인은 (+)로 쓸 수 없습니다. 조건 양쪽에 붙이면 ORA-01468 오류가 나므로 FULL OUTER JOIN으로 씁니다.
예제
네 조인은 INNER JOIN 자리의 키워드만 다르고, 결과는 그림의 표와 같습니다.
SELECT E.EMPNO,
E.ENAME,
D.DEPTNO,
D.DNAME
FROM EMP E
INNER JOIN DEPT D
ON E.DEPTNO = D.DEPTNO
ORDER BY E.EMPNO;
| EMPNO | ENAME | DEPTNO | DNAME |
|---|---|---|---|
| 1001 | 김민준 | 10 | 기획 |
| 1002 | 이서연 | 20 | 개발 |
| 1003 | 박지호 | 20 | 개발 |
| 1004 | 최유나 | 30 | 영업 |
| 1006 | 강도윤 | 20 | 개발 |
쉼표와 WHERE로 쓴 내부 조인입니다. 결과는 위와 같은 5행입니다.
SELECT E.EMPNO,
E.ENAME,
D.DEPTNO,
D.DNAME
FROM EMP E, DEPT D
WHERE E.DEPTNO = D.DEPTNO
ORDER BY E.EMPNO;
(+)로 쓴 외부 조인입니다. EMP의 행이 모두 남아 LEFT OUTER JOIN과 같은 6행입니다.
SELECT E.EMPNO,
E.ENAME,
D.DEPTNO,
D.DNAME
FROM EMP E, DEPT D
WHERE E.DEPTNO = D.DEPTNO(+)
ORDER BY E.EMPNO;
| EMPNO | ENAME | DEPTNO | DNAME |
|---|---|---|---|
| 1001 | 김민준 | 10 | 기획 |
| 1002 | 이서연 | 20 | 개발 |
| 1003 | 박지호 | 20 | 개발 |
| 1004 | 최유나 | 30 | 영업 |
| 1005 | 정하늘 | NULL | NULL |
| 1006 | 강도윤 | 20 | 개발 |
시험 포인트
- 조인 열이 NULL인 행은 어떤 값과도 짝이 되지 않아 내부 조인에서 늘 빠집니다.
- LEFT는 JOIN 왼쪽, RIGHT는 오른쪽 테이블의 행을 모두 남깁니다. 테이블 자리를 바꾸면 LEFT와 RIGHT도 바뀝니다.
- 행 수는 내부 조인 행에 남긴 짝 없는 행을 더한 수입니다.
- 두 테이블에 다 있는 열은
E.DEPTNO처럼 밝히고, 별칭을 붙였으면EMP.ENAME이 아니라E.ENAME으로 씁니다. Oracle은 테이블 별칭 앞에 AS를 쓸 수 없습니다. - Oracle
(+)는 NULL로 채워지는 쪽 열에 붙이고, 반대쪽 테이블의 행이 모두 남습니다. 완전 외부 조인은(+)로 쓸 수 없습니다.
확인 문제
1. 다음 쿼리는 무엇을 찾는 쿼리이고, 결과는 무엇일까요?
SELECT E.EMPNO,
E.ENAME
FROM EMP E
LEFT OUTER JOIN DEPT D
ON E.DEPTNO = D.DEPTNO
WHERE D.DEPTNO IS NULL;
정답
부서와 짝이 없는 사원을 찾는 쿼리입니다.
| EMPNO | ENAME |
|---|---|
| 1005 | 정하늘 |
LEFT OUTER JOIN 결과에서 DEPT 쪽 칸이 NULL인 줄은 짝이 없던 정하늘 줄뿐입니다.
2. DEPT에 소속 사원이 없는 50번 총무 부서를 하나 더 넣으면, 네 조인의 결과는 각각 몇 행일까요?
정답
50번 부서는 40번처럼 짝이 없는 DEPT 행이 됩니다. 그래서 DEPT의 행을 모두 남기는 RIGHT와 FULL만 한 행씩 늘어납니다.
INNER 5행 · LEFT 6행 · RIGHT 7행 · FULL 8행입니다. 넣는 문장은 아래와 같습니다.
INSERT INTO DEPT
VALUES (50, '총무',
'대전');3. 다음 Oracle 쿼리를 표준 조인으로 바꾸려고 합니다.
SELECT E.EMPNO,
E.ENAME,
D.DEPTNO,
D.DNAME
FROM EMP E, DEPT D
WHERE E.DEPTNO(+) = D.DEPTNO
ORDER BY E.EMPNO;
바꾼 쿼리의 FROM 절은 아래 꼴입니다. 빈칸에 들어갈 조인은 무엇이고, 결과는 몇 행일까요?
FROM EMP E
______ DEPT D
ON E.DEPTNO = D.DEPTNO
정답
RIGHT OUTER JOIN이고, 결과는 6행입니다.
(+)가 EMP 쪽에 붙었으니 EMP 쪽이 NULL로 채워지고, (+)가 없는 DEPT의 행이 모두 남습니다.
빈칸 왼쪽이 EMP이므로, 오른쪽 DEPT를 모두 남기는 RIGHT OUTER JOIN이 됩니다.
| EMPNO | ENAME | DEPTNO | DNAME |
|---|---|---|---|
| 1001 | 김민준 | 10 | 기획 |
| 1002 | 이서연 | 20 | 개발 |
| 1003 | 박지호 | 20 | 개발 |
| 1004 | 최유나 | 30 | 영업 |
| 1006 | 강도윤 | 20 | 개발 |
| NULL | NULL | 40 | 인사 |
