1. 표준조인(STANDARD JOIN)
2. FROM 절 JOIN 형태
3. INNER JOIN
4. NATURAL JOIN
5. USING 조건절
6. ON 조건절
7. CROSS JOIN
8. OUTER JOIN
9. INNER vs OUTER vs CROSS JOIN 비교
1. UNION 연산은 UNION 기능으로, (수학적 합집합 , UNION ALL은 공통집합을 중복해서 보여주기때문에 정렬 작업이 없는 장점을 가진다.)
2. INTERSECTION 연산은 INTERSECT 기능으로, (수학의 교집합, 두 집합의 공통집합을 추출한다.)
3. DIFFERENCE 연산은 EXCEPT(ORACLE MINUS)기능으로, (대다수 벤더는 EXCEPT SQL 표준 ORACLE은 MINUS 사용)
4. PRODUCT 연산은 CROSS JOIN 기능으로 구현되었다. (양쪽 집합의 M*N건의 데이터 조합 , CARTESIAN PRODUCT 라고도 표현 )
5. SELECT 연산은 WHERE 절로 구현되었다.
6. PROJECT 연산은 SELECT 절로 구현되었다.
7. (NATURAL) JOIN 연산은 다양한 JOIN 기능으로 구현되었다.
8. DIVIDE 연산은 현재 상용하지 않는다.
*JOIN 조건에서 동일한 값이 있는 행만 반환한다
<예제>
WHERE 절 JOIN 조건
SELECT EMP.DEPTNO, EMPNO, ENAME, DNAME
FROM EMP, DEPT
WHERE EMP.DEPTNO = DEPT.DEPTNO;
위 SQL과 아래 SQL은 같은 결과를 얻을 수 있다.
FROM 절 JOIN 조건
SELECT EMP.DEPTNO, EMPNO, ENAME, DNAME
FROM EMP INNER JOIN DEPT
ON EMP.DEPTNO = DEPT.DEPTNO;
--INNER는 JOIN의 디폴트 옵션으로 아래 SQL문과 같이 생략 가능하다.
SELECT EMP.DEPTNO, EMPNO, ENAME, DNAME
FROM EMP JOIN DEPT
ON EMP.DEPTNO = DEPT.DEPTNO;
<예제>
SELECT DEPTNO, EMPNO, ENAME, DNAME
FROM EMP NATURAL JOIN DEPT;
SELECT EMP.DEPTNO, EMPNO, ENAME, DNAME
FROM EMP NATURAL JOIN DEPT;
-- ORA-25155: NATURAL JOIN에 사용된 열은 식별자를 가질 수 없음
아래 '*' 와일드카드처럼 별도의 칼럼 순서를 지정하지 않으면 NATURAL JOIN의 기준이 되는 칼럼 들이 다른 칼럼보다 먼저 출력된다
SELECT * FROM EMP NATURAL JOIN DEPT;
<예제>
SELECT * FROM DEPT JOIN DEPT_TEMP USING (DEPTNO);
SELECT a.DEPTNO, a.DNAME, a.LOC, b.DNAME, b.LOC
FROM DEPT a JOIN DEPT b USING (DEPTNO);
-- ORA-25154: USING 절의 열 부분은 식별자를 가질 수 없음
SELECT DEPTNO, DEPT.DNAME, DEPT.LOC, DEPT_TEMP.DNAME, DEPT_TEMP.LOC
FROM DEPT JOIN DEPT_TEMP USING (DEPTNO);
SELECT E.EMPNO, E.ENAME, E.DEPTNO, D.DNAME
FROM EMP E JOIN DEPT D ON (E.DEPTNO = D.DEPTNO);
가) WHERE 절과의 혼용
SELECT E.ENAME, E.DEPTNO, D.DEPTNO, D.DNAME
FROM EMP E JOIN DEPT D ON (E.DEPTNO = D.DEPTNO)
WHERE E.DEPTNO = 30;
나) ON 조건절 + 데이터 검증 조건 추가
SELECT E.ENAME, E.MGR, D.DEPTNO, D.DNAME
FROM EMP E JOIN DEPT D ON (E.DEPTNO = D.DEPTNO AND E.MGR = 7698);
--위 SQL과 아래 SQL은 같은 결과를 얻을 수 있다.
SELECT E.ENAME, E.MGR, D.DEPTNO, D.DNAME
FROM EMP E JOIN DEPT D ON (E.DEPTNO = D.DEPTNO) WHERE E.MGR = 7698;
다) ON 조건절 예제
SELECT TEAM_NAME, TEAM.STADIUM_ID, STADIUM_NAME
FROM TEAM JOIN STADIUM ON TEAM.STADIUM_ID = STADIUM.STADIUM_ID
ORDER BY STADIUM_ID;
-- 위 SQL은 STADIUM_ID라는 공통된 칼럼이 있기 때문에 아래처럼 USING 조건절로 구현할 수도 있다.
SELECT TEAM_NAME, STADIUM_ID, STADIUM_NAME
FROM TEAM JOIN STADIUM USING (STADIUM_ID) ORDER BY STADIUM_ID ;
--위 SQL은 고전적인 방식인 WHERE 절의 INNER JOIN으로 구현할 수도 있다.
SELECT TEAM_NAME, TEAM.STADIUM_ID, STADIUM_NAME
FROM TEAM, STADIUM WHERE TEAM.STADIUM_ID = STADIUM.STADIUM_ID ORDER BY STADIUM_ID
라) 다중 테이블 JOIN
SELECT E.EMPNO, D.DEPTNO, D.DNAME, T.DNAME New_DNAME
FROM EMP E JOIN DEPT D ON (E.DEPTNO = D.DEPTNO)
JOIN DEPT_TEMP T ON (E.DEPTNO = T.DEPTNO);
--위 SQL은 고전적인 방식인 WHERE 절의 INNER JOIN으로 구현할 수도 있다.
SELECT E.EMPNO, D.DEPTNO, D.DNAME, T.DNAME New_DNAME
FROM EMP E, DEPT D, DEPT_TEMP T
WHERE E.DEPTNO = D.DEPTNO AND E.DEPTNO = T.DEPTNO;
SELECT COUNT(*) FROM EMP ; -- 14건
SELECT COUNT(*) FROM DEPT ; -- 4건
SELECT ENAME, DNAME FROM EMP CROSS JOIN DEPT ORDER BY ENAME ; -- 56건
SELECT E.ENAME, D.DEPTNO, D.DNAME
FROM EMP E LEFT OUTER JOIN DEPT D ON E.DEPTNO = D.DEPTNO;
SELECT E.ENAME, D.DEPTNO, D.DNAME
FROM EMP E RIGHT OUTER JOIN DEPT D ON E.DEPTNO = D.DEPTNO;
SELECT *
FROM DEPT FULL OUTER JOIN DEPT_TEMP
ON DEPT.DEPTNO = DEPT_TEMP.DEPTNO
-- 퀴즈
-- 다음중 결과값이 다른 쿼리는?
WITH T1 (idx , col1 , col2 ) AS (
SELECT '1','10','100' FROM DUAL UNION ALL
SELECT '2','20','200' FROM DUAL UNION ALL
SELECT '3','30','300' FROM DUAL UNION ALL
SELECT '4','40','400' FROM DUAL UNION ALL
SELECT '5','50','500' FROM DUAL
) , T2 ( idx , col1 , co2 ) AS (
SELECT '1','10','100' FROM DUAL UNION ALL
SELECT '2','20','200' FROM DUAL UNION ALL
SELECT '3','30','300' FROM DUAL
)
/*-- 1번쿼리
SELECT *
FROM T1 a LEFT OUTER JOIN T2 b
ON a.idx = b.idx
AND a.idx IN (1,2)
AND b.col1 = 10 */
-----------------------------
/*-- 2번쿼리
SELECT *
FROM T1 a LEFT OUTER JOIN T2 b
ON a.idx = b.idx
WHERE a.idx IN (1,2)
AND b.col1 = 10 */
-----------------------------
/*-- 3번쿼리
SELECT *
FROM T1 a LEFT OUTER JOIN T2 b
ON a.idx = b.idx
AND a.idx IN (1,2)
WHERE b.col1 = 10 */
-----------------------------
/*-- 4번 쿼리
SELECT *
FROM T1 a , T2 b
WHERE a.idx = b.idx(+)
AND a.idx in (1,2)
AND b.col1 = 10 */
-------------------------------