본문 바로가기

Oracle

[210923] JOIN

JOIN


하나 이상의 테이블에서 데이터를 조회하기 위해 사용

행에 대한 집합 연산자와 다르게 수행 결과는 하나의 Result Set(열)으로 나온다

 

- 열에 대한 결합 (수평 확장) 

- 컬럼명이 달라도 상관 없다 결합 조건만 맞으면 됨. 단, 컬럼명이 동일할 경우 구분이 헷갈리므로 컬럼명 앞에 테이블 이름 붙이는 것

JOIN

 

JOIN 오라클 전용 구문

- FROM절에 ‘,’로 구분하여 합치게 될 테이블 명을 기술하고 WHERE절에 합치기에 사용할 컬럼 명 명시

SELECT EMP_ID, EMP_NAME, EMPLOYEE.JOB_CODE, JOB_NAME
FROM EMPLOYEE, JOB
WHERE EMPLOYEE.JOB_CODE = JOB.JOB_CODE;

* 연결에 사용할 두 컬럼 명이 같은 경우 테이블명.컬럼명으로 작성하여 구분

SELECT EMP_ID, EMP_NAME, E.JOB_CODE, JOB_NAME
FROM EMPLOYEE E, JOB J
WHERE E.JOB_CODE = J.JOB_CODE;
* FROM절에 사용한 테이블 별칭 이용 가능



A라는 테이블과 B라는 테이블의 서로 동일한 것들끼리만 결합 시킨다.
A 테이블의 부서코드와 B테이블의 부서코드가 동일한 것끼리만 결합을 시키고 있는 것이다.
조건에 해당하는 동일한 것들(JOB_CODE)은 하나로 합쳐진다고 생각하면 됨

 

JOIN ANSI 표준 구문

- 연결에 사용하려는 컬럼 명이 같은 경우 USING() 사용, 다른 경우 ON() 사용

SELECT EMP_ID, EMP_NAME, JOB_CODE, JOB_NAME
FROM EMPLOYEE
JOIN JOB USING(JOB_CODE);

권장
SELECT EMP_ID, EMP_NAME, DEPT_CODE, DEPT_TITLE
FROM EMPLOYEE
JOIN DEPARTMENT ON(DEPT_CODE = DEPT_ID);

ex)

SELECT EMPLOYEE_IDFIRST_NAMELAST_NAMEDEPARTMENT_ID  -- 1 : 열 3개
FROM EMPLOYEES



SELECT DEPARTMENT_IDDEPARTMENT_NAME  -- 2 : 열 2개
FROM DEPARTMENTS;


SELECT EMPLOYEE_ID    -- 1, 2 테이블을 DEPARTMENT_ID 기준으로 조인 : 열 5개
     , FIRST_NAME
     , LAST_NAME
     , EMPLOYEES.DEPARTMENT_ID
     , DEPARTMENT_NAME
FROM EMPLOYEES JOIN DEPARTMENTS 
  ON EMPLOYEES.DEPARTMENT_ID = DEPARTMENTS.DEPARTMENT_ID
ORDER BY 1;

-- 상기 동일, 테이블 별칭 이용 
SELECT EMPLOYEE_ID
     , FIRST_NAME
     , LAST_NAME
     , E.DEPARTMENT_ID
     , DEPARTMENT_NAME
FROM EMPLOYEES E JOIN DEPARTMENTS D 
  ON E.DEPARTMENT_ID = D.DEPARTMENT_ID
ORDER BY 1;


-- 여러 테이블 조인(JOBS 추가)
SELECT EMPLOYEE_ID
     , FIRST_NAME
     , LAST_NAME
     , A.DEPARTMENT_ID
     , DEPARTMENT_NAME
     A.JOB_ID
     , JOB_TITLE
FROM EMPLOYEES A JOIN DEPARTMENTS B 
  ON A.DEPARTMENT_ID = B.DEPARTMENT_ID
  JOIN JOBS C       -- JOBS 테이블
    ON A.JOB_ID = C.JOB_ID  -- JOB_ID 기준으로 조인
ORDER BY 1;

 

INNER JOIN과 OUTER JOIN

기본적으로 JOIN은 INNER JOIN이며 두 개 이상의 테이블을 조인할 때 일치하는 값이 없는 행은 조인에서 제외됨
OUTER JOIN은 일치하지 않은 값도 포함이 되며 반드시 OUTER JOIN 명시

결합 조건을 만족시키지 못하더라도 어쨌든 출력 되게 하고 싶은 경우 (한 부분이 NULL이더라도)

 

1. LEFT OUTER JOIN
합치기에 사용한 두 테이블 중 왼쪽에 기술된 테이블의 컬럼 수를 기준으로 JOIN할 때


2. RIGHT OUTER JOIN
합치기에 사용한 두 테이블 중 오른쪽에 기술된 테이블의 컬럼 수를 기준으로 JOIN할 때


3. FULL OUTER JOIN
합치기에 사용한 두 테이블이 가진 모든 행을 결과에 포함시킬 때

 

OUTER JOIN ex)  

SELECT
 EMPLOYEE_ID

     , FIRST_NAME
     , LAST_NAME
     , A.DEPARTMENT_ID
     , DEPARTMENT_NAME
     , A.JOB_ID
     , JOB_TITLE
FROM EMPLOYEES A JOIN DEPARTMENTS B 
  ON A.DEPARTMENT_ID = B.DEPARTMENT_ID
  JOIN JOBS C       
    ON A.JOB_ID = C.JOB_ID 
 WHERE EMPLOYEE_ID = 178;       
--EMPLOYEE_ID = 178 인부분의 DEPARTMENT_ID가 NULL이라 조인 조건을 만족시키지 못하는 경우 값 출력 안 됨

ORDER BY 1;

SELECT EMPLOYEE_ID
     , FIRST_NAME
     , LAST_NAME
     , A.DEPARTMENT_ID
     , DEPARTMENT_NAME
     , A.JOB_ID
     , JOB_TITLE
FROM EMPLOYEES A LEFT OUTER JOIN DEPARTMENTS B
-- NULL이라서 JOIN에서 제외 된 값도 출력되게 하고 싶을 때 (LEFT/ RIGTH/FULL) OUTER JOIN 

  ON A.DEPARTMENT_ID = B.DEPARTMENT_ID 
-- ON 등호 기준 왼쪽 테이블(EMPLOYEES)의 결합 조건 값이 NULL이더라도 나오게 하겠다 LEFT  

  JOIN JOBS C       
    ON A.JOB_ID = C.JOB_ID 
 WHERE EMPLOYEE_ID = 178;       
ORDER BY 1;
OUTER JOIN
-- LEFT RIGHT FULL ex)


SELECT EMPLOYEE_ID
     , FIRST_NAME
     , LAST_NAME
     , A.DEPARTMENT_ID
     , DEPARTMENT_NAME
FROM EMPLOYEES A RIGHT OUTER JOIN DEPARTMENTS B  -- 오른쪽 테이블 조건 값이 해당하므로 결과 출력 안 된다
  ON A.DEPARTMENT_ID = B.DEPARTMENT_ID
 WHERE EMPLOYEE_ID = 178;       
ORDER BY 1;

SELECT EMPLOYEE_ID
     , FIRST_NAME
     , LAST_NAME
     , A.DEPARTMENT_ID
     , DEPARTMENT_NAME
FROM DEPARTMENTS A RIGHT OUTER JOIN EMPLOYEES B  -- 테이블 순서 뒤바꾸면 정상으로 나온다 
  ON A.DEPARTMENT_ID = B.DEPARTMENT_ID
 WHERE EMPLOYEE_ID = 178;       
ORDER BY 1;

SELECT EMPLOYEE_ID
     , FIRST_NAME
     , LAST_NAME
     , A.DEPARTMENT_ID
     , DEPARTMENT_NAME
FROM DEPARTMENTS A FULL OUTER JOIN EMPLOYEES B  -- 어느 쪽에 값이 없든 나오게 하고 싶을 때
  ON A.DEPARTMENT_ID = B.DEPARTMENT_ID
 WHERE EMPLOYEE_ID = 178;       
ORDER BY 1;

CROSS JOIN


카테시안 곱(Cartesian Product)라고도 하며 조인되는 테이블의 각 행들이 모두 매핑된 데이터가 검색되는 조인 방법
검색되는 데이터 수는 ‘행의 컬럼 수 * 또 다른 행의 컬럼 수‘로 나옴

열은 주르륵 다 결합되고 행의 갯수가 행의 컬럼 수 * 또 다른 행의 컬럼 수 (경우의 수 계산하는 것처럼)

 


NON_EQU JOIN


지정한 컬럼 값이 일치하는 경우가 아닌 값의 범위에 포함되는 행들을 연결하는 방식

범위에 대한 조인이 필요할 때 (같은 것에 대한 조인이 아니므로 NON_EQUAL 이라고 명명한 것, 쿼리 작성 식이 아님)

SELECT EMP_NAME, SALARY, E.SAL_LEVEL
FROM EMPLOYEE E
JOIN SAL_GRADE S ON (SALARY BETWEEN MIN_SAL AND MAX_SAL);
SELECT * FROM JOBS;  
--JOBS 최소 최대 급여 컬럼 있음 그 범위에 해당하는 월급을 받는 사원이 어떠한 JOB_ID를 쓰냐 NON_EQU 사용

SELECT * FROM EMPLOYEES;

SELECT A.EMPLOYEE_ID
     , A.FIRST_NAME
     , A.LAST_NAME
     , B.JOB_TITLE --보기 좋게
     , A.SALARY 
 FROM EMPLOYEES A JOIN JOBS B
   ON A.SALARY BETWEEN B.MIN_SALARY AND B.MAX_SALARY
 ORDER BY 1;


SELF JOIN


두 개 이상의 서로 다른 테이블을 연결하는 것이 아닌 같은 테이블을 조인하는 것

--SELF JOIN
SELECT * FROM EMPLOYEES;

SELECT A.EMPLOYEE_ID
     , A.FIRST_NAME
     , A.LAST_NAME
     , A.MANAGER_ID
     , B.FIRST_NAME AS MANAGER_FIRST_NAME
     , B.LAST_NAME AS MANAGER_LAST_NAME
 FROM EMPLOYEES A JOIN EMPLOYEES B
   ON A.MANAGER_ID = B.EMPLOYEE_ID   
-- EMPLOYEES 테이블에서 EMPLOYEE_ID 가 101인 사람의 상급자(MANAGER_ID)는 100이다
 -- 그러나 상급자 입장에서는 자신의 ID가 MANAGER_ID가 아닌 EMPLOYEE_ID 일 것이므로 (결합조건 겹치기가 됨)
-- SELF JOIN 이 가능, 이름을 뽑아낼 수 있게 된다.

 ORDER BY 1;        
                     
<EMPLOYEES 테이블>


<SELF JOIN 한 테이블>

다중 JOIN


하나 이상의 테이블에서 데이터를 조회하기 위해 사용하고 수행 결과는 하나의 Result Set으로 나옴

예시

SELECT EMP_ID, EMP_NAME, DEPT_CODE, DEPT_TITLE, LOCAL_NAME
FROM EMPLOYEE 
JOIN DEPARTMENT ON (DEPT_CODE = DEPT_ID)
JOIN LOCATION ON (LOCATION_ID = LOCAL_CODE);

SELECT EMP_ID, EMP_NAME, DEPT_CODE, DEPT_TITLE, LOCAL_NAME
FROM EMPLOYEE
JOIN LOCATION ON (LOCATION_ID = LOCAL_CODE)
JOIN DEPARTMENT ON (DEPT_CODE = DEPT_ID); 
* 에러, 다중 조인의 경우 조인 순서 매우 중요