본문 바로가기
sql/oracle

JOIN

by choi-dev 2024. 6. 2.

정의

JOIN은 여러 테이블을 하나처럼 사용하는 방법을 말한다. 기존에 집합을 사용했을 때랑 차이가 있다면, 집합의 경우에는 값을 세로로 연결한 것이고 조인은 값을 가로로 연결한 것이라고 생각하면 된다. 외래키 값을 이용해 테이블 간의 상관관계를 맺고 이를 각각 가로로 붙여주어서 여러 테이블을 하나의 테이블처럼 사용할 수 있는 것이다.

 

예제를 통한 조회

EMP 테이블과 DEPT 테이블을 일단 조회해보자.

 

SELECT
	*
FROM
	EMP,
	DEPT
ORDER BY
	EMPNO;

이렇게 조회를 했을 때는 엄청난 로우 데이터들이 나오는 것을 확인할 수 있다. 현재 위의 쿼리를 사용해 조회해보면 56개의 데이터들이 나온다. 왜 56개의 데이터들이 나올까? EMP 테이블에서 SMITH라는 데이터는 DEPTNO가 20으로 RESEARCH에 해당하는 데이터만 나와야하는데 전부 나왔다. 그렇기에 EMP 테이블의 로우 수(14)에 DEPT 테이블의 로우 수(4)를 곱해 56개의 로우 데이터가 나왔음을 알 수 있다.

 

SELECT
	*
FROM
	EMP,
	DEPT
WHERE 
	EMP.DEPTNO = DEPT.DEPTNO 
ORDER BY
	EMPNO;

SELECT * FROM EMP

그렇기에 위와 같은 조건을 붙여주어 테이블을 조인해주면 존재하지 않아도 조회되었던 부분은 정상적으로 동작하게 됨을 알 수 있을 것이다.

 

등가 조인

사실 등가 조인이라는 말은 잘 몰랐는데 똑같은 말로 내부 조인(inner join)이라고 생각하면 된다. 외부적으로 조인하는 것을 명시하지 않는다면 일반적인 조인은 이너 조인을 사용한다는 것을 알고 있으면 된다.

 

SELECT
	E.EMPNO, E.ENAME, DEPTNO, DNAME, LOC
FROM
	EMP E,
	DEPT D
WHERE 
	E.DEPTNO = D.DEPTNO 
ORDER BY
	EMPNO;

조인을 사용할 때, 이처럼 테이블의 약어를 사용하고 조회할 수도 있는 경우가 있다. DEPTNO 컬럼은 EMP 테이블, DEPT 테이블 모두 가지고 있기 때문에 어떤 DEPTNO를 가져오고 싶은지는 테이블의 약어.컬럼으로 반드시 지정해주어야 한다. 그렇지 않으면 열의 정의가 애매하다 라고 답을 받게 될 것이다.

 

비등가 조인

등가 조인 외에 사용되는 조인 방식을 말한다. 예제를 통해서 조금 더 세부적으로 이를 알아보겠다. 이번에는 DETP, EMP 테이블이 아닌 EMP와 SALGRADE 테이블을 조인시켜본다 가정한다.

 

SALGRADE 테이블에는 일반 형식적인 저장이 아닌 몇과 몇 사이인 값으로 이루어져 있다. 이런 경우의 조인은 어떻게 해야할까? 참고로 EMP 테이블은 SAL의 값만 존재한다. 이런 경우에 비등가 조인을 사용하는 것이다.

 

SELECT
	*
FROM
	EMP E,
	SALGRADE S
WHERE
	E.SAL BETWEEN S.LOSAL AND S.HISAL

실무에서는 이런 방식을 잘 사용하지는 않는다. 하지만 위의 예제처럼 특정 열의 일치 여부를 가지고도 조인이 가능한 점 정도는 알고 있는 것이 좋다. 

 

자체 조인

EMP 테이블을 가지고 자체 조인에 대해서 알아보겠다. EMP 테이블의 프로퍼티들을 보면 MGR이라고 하는 항목이 있다. MGR의 경우는 상관의 EMP 번호를 가지고 있는 것이라고 생각하면 된다. 즉,  EMP 테이블을 자체적으로 EMPNO와 MGR을 사용해서 조인해 사용할 수 있다는 의미이다. 자체 조인을 하는 방법에는 두 가지가 있다.

 

SELECT
	*
FROM
	EMP E,
	COPY_EMP CE
WHERE
	E.MGR = CE.EMPNO

 

첫번째는 EMP 테이블의 복사본을 생성하고 그것을 조인시키는 방법이다. 하지만 이 방식에는 문제가 있는 것이 EMP 테이블과 COPY_EMP 테이블의 데이터가 항상 같아야 한다는 점이다. 또한 데이터베이스 서버 내에 동일하지만 이름이 다른 테이블이 존재해야된다는 것이다.

 

SELECT
	*
FROM
	EMP E,
	EMP E2
WHERE
	E.MGR = E2.EMPNO

두번째 방법은 약어를 바꿔주는 것이다. 이렇게 테이블 내의 PK 값을 외래키로써 가지고 있는 경우에도 자체쿼리를 사용해 조인을 할 수 있다는 걸 알 수 있다.

 

외부 조인

자체 조인의 예제 결과는 EMP 테이블을 조인했지만 로우의 수는 13개임을 확인할 수 있다. 그 이유는 EMP 테이블의 KING 데이터의 MGR은 NULL이기 때문인데 상식적으로 PRESIDENT의 상급자는 존재하지 않기 때문에 일어난 것이기에 최종 출력에서 제외된 것이다.

 

하지만 실질적으로 어느 한쪽이 NULL이어도 결과를 출력할 때 포함시켜야하는 경우가 종종 존재하는데 조인의 수행이 이루어짐에 있어서 NULL이 있더라도 강제적으로 출력하는 방식을 외부 조인이라고 한다. 외부 조인은 왼쪽, 오른쪽을 나누어 지정하는데 이는 예제를 통해 알아보겠다.

 

SELECT
	*
FROM
	EMP E,
	EMP E2
WHERE
	E.MGR = E2.EMPNO(+)

왼쪽 외부 조인을 사용하는 쿼리이다.

 

SELECT
	*
FROM
	EMP E,
	EMP E2
WHERE
	E.MGR(+) = E2.EMPNO

오른쪽 외부 조인을 사용하는 쿼리이다. 위의 쿼리와 아래의 쿼리 차이를 쿼리 질의로 한 번 분석해보겠다.

 

SELECT
	*
FROM
	EMP E,
	EMP E2
WHERE
	E.MGR = E2.EMPNO(+)

이 쿼리는 왼쪽의 EMP 테이블의 MGR 컬럼이 NULL이어도 오른쪽의 EMP 테이블의 EMPNO 로우를 모두 출력하라는 뜻이다. 즉, 맨 처음에 자체 조인을 사용할 때 KING에 해당하는 로우는 MGR이 NULL이기에 내부 조인으로 출력되지 않은 정보가 외부 조인으로 변경되며 출력되게 된다.

 

SELECT
	*
FROM
	EMP E,
	EMP E2
WHERE
	E.MGR(+) = E2.EMPNO

이 쿼리를 보자. 오른쪽 EMP 테이블의 EMPNO가 NULL이어도 왼쪽 EMP 테이블의 로우를 모두 출력하라는 의미이다. 이건 이해가 좀 잘 안 될수도 있다.

 

조회 결과가 조금 짤리긴했는데 이런 결과를 얻을 수 있다. 이 경우는 EMP 테이블의 사원 중 현재 본인이 상급자인 경우가 아닌 로우들이 저렇게 나오는 것이다.

 

왼쪽, 오른쪽 조인에 대해서는 정확히 의미를 알고 넘어가는 것이 좋긴 하지만 좌우로 번갈아가면서 사용해 원하는 값이 제대로 도출되는지 확인하는 것도 일종의 한 가지 방법이 될 수 있다. 

 

표준 문법으로 조인(내부 조인)

SQL문이 ISO에서 관계형 데이터베이스 표쥰 언어로 지정되면서 SQL-99 표준 문법이 생겨났고 그에 따라서 문법이 조금씩 변화하거나 추가된 것이 있고 현재 단락에서 적을 조인 문법 또한 추가되어 어떻게 조인하고 있는지 확인해보겠다.

 

첫번째 방식은 NATURAL JOIN이다.

 

SELECT
	E.EMPNO,
	E.ENAME,
	E.JOB,
	E.SAL,
	E.COMM,
	DEPTNO,
	D.DNAME,
	D.LOC
FROM
	EMP E,
	DEPT D
ORDER BY
	DEPTNO,
	E.EMPNO

기존에는 이렇게 하면 중복되는 컬럼으로 인해 에러가 발생했다.

 

SELECT
	E.EMPNO,
	E.ENAME,
	E.JOB,
	E.SAL,
	E.COMM,
	DEPTNO,
	D.DNAME,
	D.LOC
FROM
	EMP E
NATURAL JOIN 
	DEPT D
ORDER BY
	DEPTNO,
	E.EMPNO

NATURAL JOIN이라는 것을 사용하게 되면 공통열 DEPTNO을 통해 자동적으로 그것을 통해 등가 조인 처리가 된다. 하지만 NATURAL JOIN의 경우에는 공통되는 DEPTNO 같은 것에 앞에 테이블 이름을 명시하면 안된다.

 

두번째 방식은 JOIN ~ USING이다.

 

SELECT
	E.EMPNO,
	E.ENAME,
	E.JOB,
	E.SAL,
	E.COMM,
	DEPTNO,
	D.DNAME,
	D.LOC
FROM
	EMP E
JOIN 
	DEPT D
USING
	(DEPTNO)
ORDER BY
	DEPTNO,
	E.EMPNO

JOIN에 조인할 테이블과 어떤 컬럼을 기준으로 조인할 것인지 USING을 통해 적어준다. NATURAL JOIN 때와 마찬가지로 DEPTNO에 테이블의 이름을 명시해주지 않는다.

 

마지막은 JOIN ~ ON이다. 아마 이 방법을 가장 많이 봐왔을 것이라 생각한다.

 

SELECT
	E.EMPNO,
	E.ENAME,
	E.JOB,
	E.SAL,
	E.COMM,
	D.DNAME,
	D.LOC
FROM
	EMP E
JOIN 
	DEPT D
ON
	E.DEPTNO = D.DEPTNO 
ORDER BY
	E.DEPTNO,
	E.EMPNO

JOIN ~ USING과 비슷하지만 ON 뒤에는 테이블을 명시해준다. 또한 ORDER BY에 어떤 테이블을 토대로 정렬할 것인지 적어주어야 하고 조회하는 컬럼 영역에서 중복되는 DEPTNO을 제거해준다.

 

표준 문법으로 조인(외부 조인)

외부 조인을 사용하는 것은 크게 어렵지 않다.

 

SELECT
	E1.EMPNO,
	E1.ENAME,
	E1.MGR,
	E2.EMPNO AS MGR_EMPNO,
	E2.ENAME AS MGR_ENAME
FROM
	EMP E1
LEFT OUTER JOIN EMP E2 ON
	E1.MGR = E2.EMPNO
ORDER BY
	E1.EMPNO;

왼쪽 조인의 경우는 위와 같이 작성한다.

 

SELECT
	E1.EMPNO,
	E1.ENAME,
	E1.MGR,
	E2.EMPNO AS MGR_EMPNO,
	E2.ENAME AS MGR_ENAME
FROM
	EMP E1
RIGHT OUTER JOIN EMP E2 ON
	E1.MGR = E2.EMPNO
ORDER BY
	E1.EMPNO;

오른쪽 조인의 경우에는 다음과 같이 작성한다.

 

크게 어렵진 않지만 오른쪽 조인의 경우는 조금 더 생각을 해보아야겠다.

'sql > oracle' 카테고리의 다른 글

INSERT  (0) 2024.08.11
서브쿼리  (0) 2024.07.31
GROUP BY 함수  (0) 2024.05.06
GROUP BY  (0) 2024.05.05
데이터 처리 및 가공 함수  (0) 2024.04.14