조인은 여러 테이블의 데이터를 사용하여 동시에 출력하거나 참조할 때 사용하는 기법이다.
EQUI JOIN(등가 JOIN)
SELECT e.empno, e.ename, d.dname
FROM emp e, dept d
WHERE e.deptno = d.deptno;
NON EQUI JOIN(비등가 JOIN)
SELECT e.ename, e.sal, s.grade
FROM emp e, salgrade s
WHERE e.sal BETWEEN s.losal AND s.hisal;
INNER JOIN(내부 조인)
OUTER JOIN(외부 조인)
-- ORACLE 구문
SELECT e.ename, d.dname
FROM emp e, dept d
WHERE e.deptno = d.deptno(+); -- (+) 의 반대편이 기준 : LEFT OUTER JOIN
-- ANSI 표준 구문
SELECT e.ename, d.dname
FROM dept d LEFT OUTER JOIN emp e
ON d.deptno = e.deptno;
SELF JOIN(자체 조인)
하나의 테이블을 두 번 이상 참조하여 자신과 조인
SELECT e1.ename AS "사원명", e2.ename AS "관리자명"
FROM emp e1, emp e2
WHERE e1.mgr = e2.empno;
CROSS JOIN(교차 조인)
조인 조건 없이 두 테이블의 모든 조합을 출력(카르티시안 곱)
SELECT e.ename, d.dname
FROM emp e CROSS JOIN dept d;
SELECT e.empno, e.ename, d.dname
FROM emp e INNER JOIN dept d
ON e.deptno = d.deptno;
-- LEFT OUTER JOIN
SELECT s.name, p.name AS "지도교수"
FROM student s LEFT OUTER JOIN professor p
ON s.profno = p.profno
WHERE s.grade IN (1, 2);
-- RIGHT OUTER JOIN
SELECT s.name, p.name AS "지도교수"
FROM student s RIGHT OUTER JOIN professor p
ON s.profno = p.profno;
-- FULL OUTER JOIN
SELECT s.name, p.name AS "지도교수"
FROM student s FULL OUTER JOIN professor p
ON s.profno = p.profno;
SELECT e.ename, dname
FROM emp e NATURAL JOIN dept;
ON과 USING으로 특정 칼럼에 대해 지정하지 못한다.SELECT e.ename, dname
FROM emp e JOIN dept
USING (deptno); -- 괄호 필수
서브쿼리는 하나의 SQL 문 안에 포함된 또 다른 SQL 문을 의미한다. 반드시 괄호로 묶어야 한다.
서브쿼리가 메인쿼리와 독립적으로 실행된다.
SELECT ename, sal
FROM emp
WHERE sal > (SELECT AVG(sal) FROM emp);
서브쿼리가 메인쿼리의 컬럼을 참조한다.
SELECT e1.ename, e1.sal, e1.deptno
FROM emp e1
WHERE e1.sal > (SELECT AVG(e2.sal) FROM emp e2 WHERE e2.deptno = e1.deptno);
SELECT 절에 사용하는 서브쿼리로, 단일 값만 반환해야 한다.
SELECT e.empno, e.ename,
(SELECT d.dname FROM dept d WHERE d.deptno = e.deptno) AS dname
FROM emp e;
FROM 절에 사용하는 서브쿼리로, 테이블처럼 사용된다.
SELECT a.empno, a.ename, a.sal, a.deptno, b.deptno, b.max_sal
FROM emp a,
(SELECT deptno, MAX(sal) AS max_sal FROM emp GROUP BY deptno) b
WHERE a.deptno = b.deptno AND a.sal = b.max_sal;
서브쿼리 결과가 1개의 행만 반환한다.
SELECT ename, sal
FROM emp
WHERE sal > (SELECT AVG(sal) FROM emp);
서브쿼리 결과가 여러 행을 반환한다.
SELECT ename, sal
FROM emp
WHERE deptno IN (SELECT deptno FROM dept WHERE loc = 'SEOUL');
-- sal > ANY(1000, 2000, 3000)은 sal > 1000과 동일
SELECT ename, sal FROM emp WHERE sal > ANY(SELECT sal FROM emp WHERE deptno = 10);-- sal > ALL(1000, 2000, 3000)은 sal > 3000과 동일
SELECT ename, sal FROM emp WHERE sal > ALL(SELECT sal FROM emp WHERE deptno = 10);SELECT deptno, dname FROM dept d
WHERE EXISTS (SELECT 1 FROM emp e WHERE e.deptno = d.deptno);서브쿼리 결과가 여러 컬럼을 반환한다.
SELECT ename, sal, deptno
FROM emp
WHERE (deptno, sal) IN (SELECT deptno, MAX(sal) FROM emp GROUP BY deptno);
-- 직원이 있는 부서만 조회
SELECT deptno, dname
FROM dept d
WHERE EXISTS (SELECT 1 FROM emp e WHERE e.deptno = d.deptno);
-- 직원이 없는 부서만 조회
SELECT deptno, dname
FROM dept d
WHERE NOT EXISTS (SELECT 1 FROM emp e WHERE e.deptno = d.deptno);