[Oracle] JOIN

주재완·2024년 2월 21일
0

[Old] Oracle

목록 보기
5/10
post-thumbnail

Introduction

지금까지는 데이터를 조회할 때 테이블 하나만을 사용하였습니다. 그런데 쿼리 한번에 테이블 단 하나만 조회하라는 법은 없습니다. 즉, 복수의 테이블을 한번에 조회가 필요할 때 사용하는 JOIN에 대해서 알아보도록 하겠습니다.

JOIN

두 개 이상의 테이블에서 데이터를 조회하고자 할 때 사용되는 구문으로 조회 결과는 하나의 결과물(Result Set)로 나옵니다.

관계형 데이터베이스에서는 중복저장을 최소화하기 위해서 최대한 쪼개서 관리합니다. 즉 최소한의 데이터를 각각의 테이블에 담고 있기 때문에 필요한 정보를 얻기 위해서는 테이블을 여러 개 조회해야 하는 일이 빈번합니다.

하지만 이전까지 우리는 단 하나의 테이블 밖에 조회하지 못했습니다. 이 JOIN으로 관계형 데이터베이스에서 SQL문을 이용한 테이블간 "관계"를 맺게 됩니다(무작정 다 조회해 오는게 아니라 각 테이블간 연결고리(외래키)를 통해 데이터를 매칭시켜 조회).

기본적으로 JOIN은 크게 오라클 전용 구문ANSI(American National Standards Institute, 미국국립표준협회) 구문으로 구분됩니다. 오라클 전용 구문은 오라클에서만 지원하는 방식이고, ANSI 구문은 다른 RDBMS에서도 적용 가능합니다.

이 두 구문을 모두 사용해서 포스팅을 이어가도록 하겠습니다. 아래 표는 두 구문에서 사용되는 용어만 간단하게 정리를 해놓은 표입니다.

오라클 전용 구문ANSI 구문
등가조인 (EQUAL JOIN)내부 조인 (INNER JOIN) - JOIN USING / ON
포괄조인 (LEFT OUTER / RIGHT OUTER)왼쪽 외부 조인 (LEFT OUTER JOIN)
오른쪽 외부 조인 (RIGHT OUTER JOIN)
전체 외부 조인 (FULL OUTER JOIN)
자체조인(SELF JOIN)JOIN ON
비등가조인(NON EQUAL JOIN)

초기 설정

이해를 위해 추가 테이블을 만들었습니다. 다음과 같이 작성해서 TABLE1, TABLE2, TABLE3를 만듭니다.

CREATE TABLE TABLE1 (
    ENG CHAR(1),
    CODE NUMBER
);

CREATE TABLE TABLE2 (
    ID NUMBER,
    KOR VARCHAR(20)
);

CREATE TABLE TABLE3 (
    CODE NUMBER,
    GRK VARCHAR(20)
);

INSERT INTO TABLE1 VALUES('A', 1);
INSERT INTO TABLE1 VALUES('B', 2);
INSERT INTO TABLE1 VALUES('C', 3);

INSERT INTO TABLE2 VALUES(1, '에이');
INSERT INTO TABLE2 VALUES(2, '비');
INSERT INTO TABLE2 VALUES(4, '디');

INSERT INTO TABLE3 VALUES(1, 'ALPHA');
INSERT INTO TABLE3 VALUES(2, 'BETA');
INSERT INTO TABLE3 VALUES(5, 'EPSILON');

TABLE 1

ENGCODE
A1
B2
C3

TABLE 2

IDKOR
1에이
2
4

TABLE 3

CODEGRK
1ALPHA
2BETA
5EPSILON

여기서 각 테이블은 모두 교집합이 CODE 또는 ID가 1,2임을 알 수 있습니다.
그리고 TABLE1에서는 C, TABLE2에서는 디, TABLE3에서는 EPSILON 이 교집합에 속하지 않습니다.

등가조인(EQUAL JOIN) / 내부조인(INNER JOIN)

연결시키는 컬럼의 값이 일치하는 행들만 조회합니다. 일치하는 값이 없는 행은 조회하지 않습니다.

오라클 전용 구문

오라클 전용 구문은 다음과 같은 형태로 작성합니다.

  • FROM절에 조회하고자하는 테이블을 나열(,로 구분)
  • WHERE절에 매칭시킬 컬럼에 대한 조건을 제시

연결할 두 컬럼명이 다른 경우(TABLE1 & 2)

SELECT ENG, KOR
FROM TABLE1, TABLE2
WHERE CODE = ID;
ENGKOR
A에이
B

연결할 두 컬럼명이 같은 경우(TABLE1 & 3)

SELECT ENG, GRK
FROM TABLE1 T1, TABLE3 T3
WHERE T1.CODE = T3.CODE;
ENGGRK
AALPHA
BBETA

ANSI 구문

ANSI 구문은 다음과 같은 형채로 작성합니다.

  • FROM절에 기준이 되는 테이블 하나를 기술합니다.
  • JOIN절에 같이 조인 하고자하는 테이블을 기술 + 매칭시킬 컬럼에 대한 조건도 기술
  • JOIN USING / JOIN ON

연결할 두 컬럼명이 다른 경우(TABLE1 & 2)

SELECT ENG, KOR
FROM TABLE1
JOIN TABLE2 ON (CODE = ID);
ENGKOR
A에이
B

연결할 두 컬럼명이 같은 경우(TABLE1 & 3)

SELECT ENG, GRK
FROM TABLE1 T1
JOIN TABLE3 T3 ON (T1.CODE = T3.CODE);
ENGGRK
AALPHA
BBETA

이 때, 컬렴명이 같을 경우 JOIN USING 사용이 가능합니다.

SELECT ENG, GRK
FROM TABLE1
JOIN TABLE3 USING (CODE);

추가조건

여기서 ENG = 'A' 인 것만 조회하려면 똑같이 WHERE문을 추가로 작성해주면 됩니다.

SELECT ENG, KOR
FROM TABLE1, TABLE2
WHERE CODE = ID AND ENG = 'A';
SELECT ENG, KOR
FROM TABLE1
JOIN TABLE2 ON (CODE = ID)
WHERE ENG = 'A';

포괄조인 / 외부조인(OUTER JOIN)

내부조인과는 다르게 두 테이블간의 JOIN시 일치하지 않는 행도 포함시켜 조회가 가능합니다. 단, 반드시 LEFT/RIGHT를 지정해야됩니다(기준테이블을 정해야합니다).

LEFT JOIN

두 테이블 중 왼편에 기술된 테이블을 기준으로 JOIN을 진행합니다.

오라클 전용 구문 - LEFT JOIN

SELECT ENG, KOR
FROM TABLE1, TABLE2
WHERE CODE = ID(+);
ENGKOR
A에이
B
C(null)

ANSI 전용 구문 - LEFT JOIN

SELECT ENG, KOR
FROM TABLE1
LEFT JOIN TABLE2 ON (CODE = ID);
ENGKOR
A에이
B
C(null)

RIGHT JOIN

두 테이블 중 왼편에 기술된 테이블을 기준으로 JOIN을 진행합니다.

오라클 전용 구문 - RIGHT JOIN

SELECT ENG, KOR
FROM TABLE1, TABLE2
WHERE CODE(+) = ID;
ENGKOR
A에이
B
(null)

ANSI 전용 구문 - RIGHT JOIN

SELECT ENG, KOR
FROM TABLE1
RIGHT JOIN TABLE2 ON (CODE = ID);
ENGKOR
A에이
B
(null)

FULL JOIN

두 테이블이 가진 모든 행을 조회할 수 있습니다. 단, 이 기능은 ANSI 전용 구문에서만 지원합니다.

SELECT ENG, KOR
FROM TABLE1
FULL JOIN TABLE2 ON (CODE = ID);
ENGKOR
A에이
B
(null)
C(null)

비등가 조인(NON EQUAL JOIN)

간단하게 일치 불일치의 여부로 테이블 3개를 이용하여 JOIN에 대해서 알아 보았습니다. 하지만 롤 티어처럼 점수 구간으로 되어 있는 데이터도 존재하는데, 이는 CODE = ID 와 같은 형태로 조회하기 어렵습니다.

사실 JOIN ON 에서 조건 작성시 보통 매칭시킬 컬럼을 작성하긴 하는데, 일반적인 WHERE문과 사실상 역할은 거의 비슷합니다. 그래서 아래 두 코드는 사실상 똑같은 코드입니다.

SELECT ENG, KOR
FROM TABLE1
JOIN TABLE2 ON (CODE = ID)
WHERE ENG = 'A';
SELECT ENG, KOR
FROM TABLE1
JOIN TABLE2 ON (CODE = ID)
AND (ENG = 'A');

그냥 AND로 조건식을 묶어 주었는데도 결과는 똑같이 나옵니다. 즉 그냥 ON 다음에 필요한 조건식을 쪽 컬럼 등가 비교가 아니더라도 가능합니다.

예를 들어 MIN_SAL과 MAX_SAL을 이용하여 SAL_LEVEL을 조회할 때 다음과 같이 적을 수 있습니다.

  • 오라클 전용 구문
SELECT EMP_NAME, SALARY, SAL_LEVEL
FROM EMPLOYEE, SAL_GRADE
WHERE SALARY BETWEEN MIN_SAL AND MAX_SAL;
  • ANSI 구문
SELECT EMP_NAME, SALARY, SAL_LEVEL
FROM EMPLOYEE
JOIN SAL_GRADE ON (SALARY BETWEEN MIN_SAL AND MAX_SAL);

자체조인(SELF JOIN)

같은 데이블을 다시한번 조인하는 경우입니다. 작성 방법은 다른 조인문들과 크게 다르지는 않지만, 컬럼 적을 때 이름을 확실히 명시해야되는 것만 조심하면 됩니다.

예를 들어 해당 직원의 사수를 같이 조회하고자 할 때, 사수가 작성된 코드는 사실상 직원의 고유 코드이기도 해서 같은 테이블을 조회해야 합니다. 활용 예시만 간단하게 보고 포스팅을 마치겠습니다.

  • 오라클 전용 구문
SELECT E.EMP_ID AS "사원사번", E.EMP_NAME AS "사원명", E.DEPT_CODE,
        M.EMP_ID AS "사수사번", M.EMP_NAME AS "사수명", M.DEPT_CODE
FROM EMPLOYEE E, EMPLOYEE M
WHERE E.MANAGER_ID = M.EMP_ID;
  • ANSI 구문
SELECT E.EMP_ID AS "사원사번", E.EMP_NAME AS "사원명", E.DEPT_CODE,
        M.EMP_ID AS "사수사번", M.EMP_NAME AS "사수명", M.DEPT_CODE
FROM EMPLOYEE E
LEFT JOIN EMPLOYEE M ON (E.MANAGER_ID = M.EMP_ID);
profile
안녕하세요! 언제나 탐구하고 공부하는 개발자, 주재완입니다.

0개의 댓글