DevLog

[SQLD] 2과목 "SQL 활용" - JOIN 파트 핵심 요약 정리 본문

이모저모/SQLD

[SQLD] 2과목 "SQL 활용" - JOIN 파트 핵심 요약 정리

김만콩 2023. 11. 15. 16:50

조인 JOIN

엔터티 간 관계와 FK를 이용하여 서로 다른 테이블을 연결하여 데이터를 참조해오는 작업.
크게 조인조건이 같을 경우(=)의 등가조인(EQUI-Join)그 외의 비등가조인(Non-EQUI Join)으로 나뉜다.

-- JOIN
-- 등가조인, 비등가조인

-- 등가조인 : A=B
SELECT * FROM EMP, DEPT; -- 두 테이블 모든 행을 결합해서 출력 (모든 경우의 수, 카티션 프로덕트)
SELECT * FROM EMP, DEPT
WHERE EMP.DEPTNO = DEPT.DEPTNO;

SELECT E.EMPNO, E.ENAME, E.SAL, D.LOC, D.DEPTNO, E.DEPTNO
FROM EMP E, DEPT D
WHERE E.DEPTNO=D.DEPTNO;

-- 비등가조인 : >, <, >=, <=, AND, OR, BETWEEN...
SELECT *
FROM EMP E, SALGRADE S
WHERE E.SAL >= S.LOSAL AND E.SAL <=  S.HISAL;

-- 세 가지 테이블 연속 조인
SELECT *
FROM EMP E, DEPT D, SALGRADE S
WHERE E.DEPTNO=D.DEPTNO
AND E.SAL BETWEEN S.LOSAL AND S.HISAL;
조인하는 법
1) `FROM ... WHERE 조인조건;` : 조인할 테이블의 모든 컬럼을 불러와서 하나의 큰 테이블로 결합
2) `(INNER) JOIN ... ON 조인조건 <AND ~>;` : 조인조건에 해당하는 경우만 골라서 결합. 공통컬럼이 중복으로 들어감
3) `(INNER) JOIN ... USING(공통컬럼명) <WHERE ~>;` : 두 테이블의 공통컬럼을 하나로 두고 결합

* ON 조인을 하면 각 테이블의 공통컬럼이 모두 살아있기 때문에 `TABLE1.공통컬럼, TABLE2.공통컬럼` 과 같이 따로따로 SELECT할 수 있지만, USING 조인을 하면 공통컬럼이 하나로 합쳐지기 때문에 테이블명으로 구분해서 SELECT할 수 없다. (그냥 공통컬럼명만 작성해서 SELECT 가능)
조인 유형 : `INNER JOIN`, `NATURAL JOIN`, `CROSS JOIN`, `OUTER JOIN`

INNER JOIN

-- (INNER) JOIN

-- ON은 무조건 JOIN과 함께
SELECT *
FROM EMP E INNER JOIN DEPT D -- INNER 생략 가능
ON E.DEPTNO=D.DEPTNO;

-- USING
-- 두 개 테이블의 조인 조건 컬럼명이 같을 때
SELECT *
FROM EMP E INNER JOIN DEPT D
USING(DEPTNO);

-- USING을 사용하면 공통 컬럼이 합쳐짐 -> SELECT할 때 테이블명 붙이면 안 됨 
SELECT E.EMPNO, E.ENAME, E.SAL, D.LOC, DEPTNO -- 공통컬럼만 테이블명 없이 조회
FROM EMP E INNER JOIN DEPT D
USING(DEPTNO);


-- 실습문제1
-- EMP, DEPT 테이블에서 DEPTNO가  30인 부서에 속하는 사원의 ENAME, DEPTNO, DNAME

-- 1) JOIN ... USING ~
SELECT ENAME, DEPTNO, DNAME
FROM EMP E JOIN DEPT D
USING(DEPTNO)
WHERE DEPTNO=30;

-- 2) JOIN ... ON ~
SELECT ENAME, E.DEPTNO, DNAME
FROM EMP E JOIN DEPT D
ON E.DEPTNO=D.DEPTNO
AND E.DEPTNO=30;


-- 실습문제2
-- 각 급여 등급별 급여 총합, 평균(소수 첫째자리까지), 사원수, 최대급여, 최소급여

-- 1) FROM ... WHERE ~
SELECT S.GRADE, SUM(E.SAL), ROUND(AVG(E.SAL), 1), COUNT(*), MAX(E.SAL), MIN(E.SAL)
FROM EMP E, SALGRADE S
WHERE E.SAL BETWEEN S.LOSAL AND S.HISAL
GROUP BY S.GRADE
ORDER BY S.GRADE;

-- 2) JOIN ... ON ~
SELECT S.GRADE, SUM(E.SAL), ROUND(AVG(E.SAL), 1), COUNT(*), MAX(E.SAL), MIN(E.SAL)
FROM EMP E JOIN SALGRADE S
ON E.SAL BETWEEN S.LOSAL AND S.HISAL
GROUP BY S.GRADE
ORDER BY 1;


-- 실습문제3
-- SCOTT 사원이 근무하고 있는 부서의 이름

SELECT * FROM EMP;
SELECT * FROM DEPT;

-- 1) ON - AND
SELECT E.ENAME, D.DNAME
FROM EMP E JOIN DEPT D
ON E.DEPTNO = D.DEPTNO
AND E.ENAME='SCOTT';

-- 2) USING - WHERE
SELECT E.ENAME, D.DNAME
FROM EMP E JOIN DEPT D
USING(DEPTNO)
WHERE E.ENAME='SCOTT';

만약 하나의 질의에서 여러 개의 테이블을 조인하더라도 JOIN은 두 개씩 묶어서 따로따로 조인

* 세 개 이상의 테이블 A, B, C를 모두 조인할 때에는
  먼저 A와 B를 조인한 후에 조인 결과를 다시 C와 조인하는 식으로 작성한다.
-- 여러 개의 테이블을 조인하는 경우

SELECT EMPNO, ENAME, SAL, DNAME, LOC
FROM EMP E JOIN DEPT D
ON E.DEPTNO=D.DEPTNO			-- 조인조건 1
JOIN SALGRADE S
ON E.SAL BETWEEN S.LOSAL AND S.HISAL	-- 조인조건 2
AND S.GRADE=4;

-- ON 뒤에 콤마가 오면 앞의 조인절 끝
SELECT EMPNO, ENAME, SAL, DNAME, LOC
FROM EMP E JOIN DEPT D
    ON E.DEPTNO=D.DEPTNO
    , SALGRADE S
    WHERE E.SAL BETWEEN S.LOSAL AND S.HISAL
AND S.GRADE=4;

 

NATURAL JOIN

공통 컬럼명을 몰라도 알아서 조인조건을 찾아서 만들어준다. (= USING 사용 결과)
ON이나 WHERE 조인조건절을 이미 포함하고 있기 때문에 따로 사용 불가 (그냥 WHERE 조건절은 가능)

SELECT *
FROM EMP E NATURAL JOIN DEPT D;

CROSS JOIN

조인조건 없이 가능한 모든 경우의 수를 다 보여준다. (= CARTITION PRODUCT)
조인조건 함께 사용 불가!

SELECT * FROM EMP, DEPT;
SELECT * FROM EMP CROSS JOIN DEPT;


SELECT * FROM A;
SELECT * FROM B;

SELECT *
FROM A, B
WHERE A.X=B.X;

SELECT *
FROM A, B
WHERE A.Y=B.Y;

SELECT *
FROM A, B
WHERE A.X=B.Y;

SELECT *
FROM A NATURAL JOIN B;

OUTER JOIN

왼쪽/오른쪽/전체 테이블을 기준으로 하는 조인 `LEFT | RIGHT | FULL OUTER JOIN`

기준 테이블에 맞춰서 조인한다.
기준이 되는 테이블의 값은 모두 출력하고 다른 테이블에 결합 대상이 없으면 NULL로 채워진다.

`LEFT OUTER JOIN`   → 왼쪽 테이블의 모든 행이 다 나옴. 오른쪽 테이블에 조인될 게 없으면 NULL로 채워짐
`RIGHT OUTER JOIN` → 오른쪽 테이블의 행이 다 나옴. 왼쪽 테이블에 조인될 게 없으면 NULL로 채워짐
`FULL OUTER JOIN`   → 양쪽 테이블의 모든 행이 다 나옴. 상대 테이블에 조인될 게 없으면 NULL로 채워짐

-- LEFT OUTER JOIN
SELECT *
FROM A LEFT OUTER JOIN B
ON A.X=B.X;

-- RIGHT OUTER JOIN
SELECT *
FROM A RIGHT OUTER JOIN B
ON A.X=B.X;

-- FULL OUTER JOIN
SELECT *
FROM A FULL OUTER JOIN B
ON A.X=B.X;

-- (+)으로 아우터 조인 작성 가능
-- LEFT OUTER는 오른쪽에, RIGHT OUTER은 왼쪽에 작성
SELECT *
FROM A JOIN B
ON A.X=B.X(+);

SELECT *
FROM A JOIN B
ON A.X(+)=B.X;