표준 조인(STANDARD JOIN)은 FROM 절에 조인 방식과 조건을 함께 씁니다. NATURAL·USING은 이름이 같은 열로, ON은 직접 쓴 조건으로 잇고, CROSS는 조건 없이 모든 행끼리 짝짓습니다.
조인의 INNER JOIN … ON처럼 FROM 절에 JOIN 키워드를 쓰는 문법은 ANSI/ISO SQL 표준입니다.
조인 조건은 ON에, 행을 거르는 조건은 WHERE에 나눠 쓸 수 있습니다.
내부 조인은 어디에 두어도 같지만, 외부 조인에서는 같은 조건이라도 ON에 두느냐 WHERE에 두느냐에 따라 결과가 달라집니다.
1NATURAL JOIN과 USING
EMP와 DEPT는 이름이 같은 열이 DEPTNO 하나라, NATURAL JOIN과 USING (DEPTNO)가 같은 5행을 냅니다.
다만 NATURAL JOIN은 이름만 같고 뜻이 다른 열이 있어도 그 열까지 같아야 잇습니다. 이을 열을 정해 두려면 USING을 씁니다.
두 방식에서 이은 열은 두 테이블의 열이 하나로 합쳐져, 그 열 앞에는 E. 같은 테이블 별칭도 EMP. 같은 테이블 이름도 붙일 수 없습니다(Oracle은 NATURAL에서 ORA-25155, USING에서 ORA-25154). DEPTNO AS D처럼 결과 열에 붙이는 별칭은 됩니다.
| 구분 | NATURAL | USING | ON |
|---|---|---|---|
| 이을 열 | 이름이 같은 열 모두 | 고른 열 | 조건으로 정함 |
그 열 앞의 테이블 별칭(E.) | 못 붙임 | 못 붙임 | 붙여서 가름 |
SELECT *의 그 열 | 맨 앞에 하나 | 맨 앞에 하나 | 테이블마다 하나 |
| SQL Server | 없음 | 없음 | 있음 |
2ON과 CROSS JOIN
ON으로 이으면 두 테이블의 DEPTNO가 따로 남으므로, SELECT에서는 D.DEPTNO처럼 어느 쪽인지 밝혀야 합니다.
열 이름이 다르거나 =가 아닌 조건으로 이을 때도 ON을 씁니다.
CROSS JOIN의 결과는 카티션 곱으로, 쉼표로 늘어놓고 조인 조건을 빼먹은 것과 같습니다. JOIN만 쓰고 ON·USING을 빠뜨린다고 CROSS JOIN이 되지는 않습니다. Oracle은 ORA-02000 오류를 냅니다.
3외부 조인에서 ON과 WHERE
LEFT OUTER JOIN의 ON에 더한 D.LOC = '서울'은 짝 후보를 서울 부서(10·40)로 좁힐 뿐이라, EMP의 행은 하나도 없어지지 않습니다.
같은 조건을 WHERE에 두면 조인을 마친 6행을 거릅니다. 판교·부산 줄과 외부 조인으로 남긴 정하늘 줄(LOC NULL)이 빠집니다.
Oracle (+)는 NULL로 채워지는 쪽의 상수 조건에도 붙여야 ON에 둔 것과 같고, 빠뜨리면 오류 없이 WHERE에 둔 것과 같아집니다.
| 조건 | 쓰이는 때 | 이 예 행 수 |
|---|---|---|
ON에 둔 D.LOC = '서울' | 짝을 고를 때 | 6 |
WHERE에 둔 D.LOC = '서울' | 조인을 마친 뒤 | 1 |
예제
NATURAL JOIN의 SELECT *입니다. 열 차례를 보려고 한 행만 골랐습니다.
SELECT *
FROM EMP
NATURAL JOIN DEPT
WHERE EMPNO = 1001;
| DEPTNO | EMPNO | ENAME | SAL | MGR | DNAME | LOC |
|---|---|---|---|---|---|---|
| 10 | 1001 | 김민준 | 520 | NULL | 기획 | 서울 |
USING으로 고른 쿼리입니다. 결과는 5행이고, E.DEPTNO로 쓰면 ORA-25154 오류입니다.
SELECT E.EMPNO,
E.ENAME,
DEPTNO,
D.DNAME
FROM EMP E
JOIN DEPT D
USING (DEPTNO)
ORDER BY E.EMPNO;
ON으로 이으면 DEPTNO가 두 번 나옵니다.
SELECT *
FROM EMP E
JOIN DEPT D
ON E.DEPTNO = D.DEPTNO
WHERE E.EMPNO = 1001;
| EMPNO | ENAME | SAL | DEPTNO | MGR | DEPTNO | DNAME | LOC |
|---|---|---|---|---|---|---|---|
| 1001 | 김민준 | 520 | 10 | NULL | 10 | 기획 | 서울 |
CROSS JOIN의 행 수입니다.
SELECT COUNT(*) AS CNT
FROM EMP
CROSS JOIN DEPT;
| CNT |
|---|
| 24 |
외부 조인의 ON에 조건을 두면 김민준 말고는 DEPT 쪽이 NULL인 6행입니다.
SELECT E.EMPNO,
E.ENAME,
D.DEPTNO,
D.DNAME,
D.LOC
FROM EMP E
LEFT OUTER JOIN DEPT D
ON E.DEPTNO = D.DEPTNO
AND D.LOC = '서울'
ORDER BY E.EMPNO;
같은 조건을 WHERE에 두면 김민준 1행만 남습니다.
SELECT E.EMPNO,
E.ENAME,
D.DEPTNO,
D.DNAME,
D.LOC
FROM EMP E
LEFT OUTER JOIN DEPT D
ON E.DEPTNO = D.DEPTNO
WHERE D.LOC = '서울'
ORDER BY E.EMPNO;
Oracle (+)로 쓰면 ON에 둔 것과 같은 6행입니다.
SELECT E.EMPNO,
E.ENAME,
D.DEPTNO,
D.DNAME,
D.LOC
FROM EMP E, DEPT D
WHERE E.DEPTNO = D.DEPTNO(+)
AND D.LOC(+) = '서울'
ORDER BY E.EMPNO;
시험 포인트
- NATURAL JOIN은 이름이 같은 열을 모두 조인 조건으로 씁니다. 뜻이 다른 열도 이름이 같으면 같아야 이어집니다.
- NATURAL JOIN과 USING에 쓰인 열 앞에는 테이블 이름이나 별칭을 붙일 수 없고,
SELECT *에서 맨 앞에 한 번 나옵니다. SQL Server에는 둘 다 없습니다. - CROSS JOIN은 카티션 곱입니다. ON·USING 없는 JOIN은 오류입니다(ORA-02000).
- 외부 조인에서 ON의 조건은 짝을 고를 뿐 기준 쪽 행을 없애지 않고, WHERE의 조건은 조인이 끝난 결과에서 행을 지웁니다. Oracle
(+)는 NULL로 채워지는 쪽의 조건 모두에 붙입니다.
확인 문제
1. Oracle에서 오류가 나는 쿼리를 고르세요.
- ①
SELECT DEPTNO FROM EMP NATURAL JOIN DEPT; - ②
SELECT E.DEPTNO FROM EMP E NATURAL JOIN DEPT D; - ③
SELECT E.ENAME FROM EMP E JOIN DEPT D USING (DEPTNO); - ④
SELECT D.DEPTNO FROM EMP E JOIN DEPT D ON E.DEPTNO = D.DEPTNO;
정답
②입니다.
NATURAL JOIN에 쓰인 DEPTNO 앞에 테이블 별칭 E.를 붙여서 ORA-25155 오류가 납니다.
③의 ENAME은 조인에 쓰이지 않아 테이블 별칭을 붙여도 되고, ④는 ON으로 이어 오히려 D.DEPTNO처럼 밝혀 써야 합니다.
2. 다음 두 쿼리는 각각 몇 행을 돌려줄까요?
SELECT E.EMPNO,
E.ENAME,
D.DNAME
FROM EMP E
LEFT OUTER JOIN DEPT D
ON E.DEPTNO = D.DEPTNO
AND D.DNAME = '개발'
ORDER BY E.EMPNO;
SELECT E.EMPNO,
E.ENAME,
D.DNAME
FROM EMP E
LEFT OUTER JOIN DEPT D
ON E.DEPTNO = D.DEPTNO
WHERE D.DNAME = '개발'
ORDER BY E.EMPNO;
정답
첫째는 6행, 둘째는 3행입니다.
첫째 쿼리는 ON에서 '개발' 부서만 짝 후보로 삼고, EMP 6행을 모두 남깁니다. 김민준·최유나·정하늘의 DNAME은 NULL입니다. 둘째 쿼리는 조인한 뒤 WHERE가 DNAME이 '개발'인 행만 남깁니다.
| EMPNO | ENAME | DNAME |
|---|---|---|
| 1002 | 이서연 | 개발 |
| 1003 | 박지호 | 개발 |
| 1006 | 강도윤 | 개발 |
3. 다음 Oracle 쿼리는 몇 행을 돌려줄까요? EMP 6행이 모두 나오게 하려면 어디를 고치면 될까요?
SELECT E.EMPNO,
E.ENAME,
D.LOC
FROM EMP E, DEPT D
WHERE E.DEPTNO = D.DEPTNO(+)
AND D.LOC = '판교'
ORDER BY E.EMPNO;
정답
3행입니다.
| EMPNO | ENAME | LOC |
|---|---|---|
| 1002 | 이서연 | 판교 |
| 1003 | 박지호 | 판교 |
| 1006 | 강도윤 | 판교 |
D.LOC = '판교'에 (+)가 없어서, 짝이 없어 LOC가 NULL로 채워진 행이 이 조건에서 빠집니다.
D.LOC(+) = '판교'로 고치면 EMP 6행이 모두 나옵니다.
표준 조인으로는 조건을 ON에 둡니다.
LEFT OUTER JOIN DEPT D
ON E.DEPTNO = D.DEPTNO
AND D.LOC = '판교'