[DB] JOIN

Brogod97·2023년 1월 14일
0

KH TIL

목록 보기
31/37
post-thumbnail

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

SELECT EMP_ID, 
			 EMP_NAME, 
			 DEPT_CODE 
FROM EMPLOYEE;

SELECT DEPT_ID, 
			 DEPT_TITLE

FROM DEPARTMENT;


JOIN 용어 정리

오라클SQL : 1999표준(ANSI)
등가 조인내부 조인(INNER JOIN), JOIN USING / ON + 자연 조인(NATURAL JOIN, 등가 조인 방법 중 하나)
포괄 조인왼쪽 외부 조인(LEFT OUTER), 오른쪽 외부 조인(RIGHT OUTER) + 전체 외부 조인(FULL OUTER, 오라클 구문으로는 사용 못함)
자체 조인, 비등가 조인JOIN ON
카테시안(카티션) 곱 (CARTESIAN PRODUCT)교차 조인(CROSS JOIN)

JOIN

  • 하나 이상의 테이블에서 데이터를 조회하기 위해 사용.
  • 수행 결과는 하나의 Result Set으로 나옴.
  • (참고) JOIN은 서로 다른 테이블의 행을 하나씩 이어 붙이기 때문에 시간이 오래 걸리는 단점이 있다!

관계형 데이터베이스에서 SQL을 이용해 테이블간 '관계'를 맺는 방법.

관계형 데이터베이스는 최소한의 데이터를 테이블에 담고 있어 원하는 정보를 테이블에서 조회하려면 한 개 이상의 테이블에서 데이터를 읽어와야 되는 경우가 많다.
이 때, 테이블간 관계를 맺기 위한 연결고리 역할이 필요한데, 두 테이블에서 같은 데이터를 저장하는 컬럼이 연결고리가됨.


기존에 서로 다른 테이블의 데이터를 조회 할 경우 아래와 같이 따로 조회함.

-- 직원번호, 직원명, 부서코드, 부서명을 조회 하고자 할 때
SELECT EMP_ID, EMP_NAME, DEPT_CODE
FROM EMPLOYEE;
-- 직원번호, 직원면, 부서코드는 EMPLOYEE테이블에 조회가능

-- 부서명은은 DEPARTMENT테이블에서 조회 가능
SELECT DEPT_ID, DEPT_TITLE
FROM DEPARTMENT;

JOIN 구문으로 작성

SELECT EMP_ID, EMP_NAME, DEPT_CODE, DEPT_TITLE
FROM EMPLOYEE
JOIN DEPARTMENT ON(DEPT_CODE = DEPT_ID); -- 등가조인, INNER JOIN

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

  • 연결되는 컬럼의 값이 일치하는 행들만 조인됨. (== 일치하는 값이 없는 행은 조인에서 제외됨.

  • 작성 방법 크게 ANSI구문과 오라클 구문 으로 나뉘고, ANSI에서USINGON을 쓰는 방법으로 나뉜다.

ANSI 표준 구문

ANSI는 미국 국립 표준 협회를 뜻함, 미국의 산업표준을 제정하는 민간단체로 국제표준화기구 ISO에 가입되어있다.

ANSI에서 제정된 표준을 ANSI라고 하고 여기서 제정한 표준 중 가장 유명한 것이 ASCII코드이다.

오라클 전용 구문

FROM절에 쉼표(,) 로 구분하여 합치게 될 테이블명을 기술하고
WHERE절에 합치기에 사용할 컬럼명을 명시한다


1) 연결에 사용할 두 컬럼명이 다른 경우

EMPLOYEE 테이블, DEPARTMENT 테이블을 참조하여 사번, 이름, 부서코드, 부서명 조회

-- ANSI
-- 연결에 사용할 컬럼명이 다른경우 ON()을 사용
SELECT EMP_ID, EMP_NAME, DEPT_CODE, DEPT_ID, DEPT_TITLE 
-- DEPT_CODE, DEPT_ID는 같은 값이라서 동일 컬럼 두개 생김
FROM EMPLOYEE
JOIN DEPARTMENT ON(DEPT_CODE = DEPT_ID);
-- 오라클
SELECT EMP_ID, EMP_NAME, DEPT_CODE, DEPT_TITLE
FROM EMPLOYEE, DEPARTMENT
WHERE DEPT_CODE = DEPT_ID;

DEPARTMENT 테이블, LOCATION 테이블을 참조하여 부서명, 지역명 조회

/*
LOCATION 테이블
LOCAL_CODE     지역코드
LOCAL_NAME     지역명
NATIONAL_CODE  국가코드

DEPARTMENT 테이블
DEPT_ID        부서코드
DEPT_TITLE     부서명
LOCATION_ID    지역코드
*/
-- ANSI 방식
SELECT DEPT_TITLE, LOCAL_NAME
FROM DEPARTMENT
JOIN LOCATION ON(LOCATION_ID = LOCAL_CODE);

-- 오라클 방식
SELECT DEPT_TITLE, LOCAL_NAME
FROM DEPARTMENT, LOCATION
WHERE LOCATION_ID = LOCAL_CODE;

2) 연결에 사용할 두 컬럼명이 같은 경우

EMPLOYEE 테이블, JOB테이블을 참조하여 사번, 이름, 직급코드, 직급명 조회

-- ANSI
-- 연결에 사용할 컬럼명이 같은 경우 USING(컬럼명)을 사용함
SELECT EMP_ID, EMP_NAME, JOB_CODE, JOB_NAME 
FROM EMPLOYEE
JOIN JOB USING(JOB_CODE);

-- 오라클 -> 별칭 사용
-- 테이블 별로 별칭을 등록할 수 있음.
SELECT EMP_ID, EMP_NAME, E.JOB_CODE, JOB_NAME -- 보통은 기준점이 되는 테이블의 컬럼을 가져옴
FROM EMPLOYEE E, JOB J
WHERE E.JOB_CODE = J.JOB_CODE;

INNER JOIN(내부 조인) 시 문제점!

연결에 사용된 컬럼의 값이 일치하지 않으면 조회 결과에 포함되지 않음 ❗


2. 외부 조인(OUTER JOIN)

두 테이블의 지정하는 컬럼값이 일치하지 않는 행도 조인에 포함을 시킴
반드시 OUTER JOIN임을 명시해야 한다.

OUTER JOIN과 비교할 INNER JOIN 쿼리문

SELECT EMP_NAME, DEPT_TITLE
FROM EMPLOYEE
/*INNER*/ JOIN DEPARTMENT ON (DEPT_CODE = DEPT_ID);

1) LEFT [OUTER] JOIN

합치기에 사용한 두 테이블 중 왼편에 기술된 테이블의 컬럼 수를 기준으로 JOIN 왼편에 작성된 테이블의 모든 행이 결과에 포함 되어야 한다 (JOIN이 안되는 행도 결과 포함)

사원의 이름과 부서명 조회

-- ANSI 표준
SELECT EMP_NAME, DEPT_TITLE
FROM EMPLOYEE LEFT JOIN DEPARTMENT
ON(DEPT_CODE = DEPT_ID); -- 23행 (하동운, 이오리 포함)

-- 오라클 구문
SELECT EMP_NAME, DEPT_TITLE
FROM EMPLOYEE, DEPARTMENT
WHERE DEPT_CODE = DEPT_ID(+);

2) RIGHT [OUTER] JOIN

합치기에 사용한 두 테이블 중 오른편에 기술된 테이블의 컬럼 수를 기준으로 JOIN

-- ANSI 표준
SELECT EMP_NAME, DEPT_TITLE
FROM EMPLOYEE RIGHT JOIN DEPARTMENT
ON(DEPT_CODE = DEPT_ID);

-- 오라클 구문
SELECT EMP_NAME, DEPT_TITLE
FROM EMPLOYEE, DEPARTMENT
WHERE DEPT_CODE(+) = DEPT_ID;

3) FULL [OUTER] JOIN

합치기에 사용한 두 테이블이 가진 모든 행을 결과에 포함

오라클 구문은 FULL OUTER JOIN을 사용 못함

-- ANSI 표준
SELECT EMP_NAME, DEPT_TITLE
FROM EMPLOYEE 
FULL JOIN DEPARTMENT ON(DEPT_CODE = DEPT_ID);

-- 오라클(X) : 오라클엔 FULL JOIN 구문이 없음

3. 교차 조인(CROSS JOIN == CARTESIAN PRODUCT)

잘 쓰이진 않는다고 함

조인되는 테이블의 각 행들이 모두 매핑된 데이터가 검색되는 방법(곱집합)
JOIN 구문을 잘못 작성하는 경우 CROSS JOIN의 결과가 조회됨

SELECT EMP_NAME, DEPT_TITLE
FROM EMPLOYEE
CROSS JOIN DEPARTMENT; -- 207행 == (EMPLOYEE) 23행 * (DEPARTMENT) 9행 = 270행

4. 비등가 조인(NON EQUAL JOIN)

잘 쓰이진 않는다고 함

=(등호)를 사용하지 않는 조인문
지정한 컬럼 값이 일치하는 경우가 아닌, 값의 범위에 포함되는 행들을 연결하는 방식

SELECT * FROM SAL_GRADE;

SELECT EMP_NAME, SAL_LEVEL FROM EMPLOYEE;

사원의 급여에 따른 급여 등급 파악하기

SELECT EMP_NAME, SALARY, SAL_GRADE.SAL_LEVEL
FROM EMPLOYEE
JOIN SAL_GRADE ON(SALARY BETWEEN MIN_SAL AND MAX_SAL);
  • 등호가 아닌 범위를 씀 == 비등가 조인

    EX) 800만원 이상 받는 사람이 무슨 등급인지 조회할 때 사용


5. 자체 조인(SELF JOIN)

같은 테이블을 조인.
자기 자신과 조인을 맺음
TIP! 같은 테이블 2개 있다고 생각하고 JOIN을 진행

사번, 이름, 사수의 사번, 사수 이름 조회

-- ANSI 표준
SELECT E1.EMP_ID, 
	   E1.EMP_NAME, 
	   NVL(E1.MANAGER_ID, '없음'), 
	   NVL (E2.EMP_NAME, '-')	
FROM EMPLOYEE E1
LEFT JOIN EMPLOYEE E2 ON(E1.MANAGER_ID = E2.EMP_ID);

-- 오라클 구문
SELECT E1.EMP_ID, 
	   E1.EMP_NAME, 
	   NVL(E1.MANAGER_ID, '없음'), 
	   NVL (E2.EMP_NAME, '-')	
FROM EMPLOYEE E1, EMPLOYEE E2
WHERE E1.MANAGER_ID = E2.EMP_ID(+);

6. 자연 조인(NATURAL JOIN)

동일한 타입과 이름을 가진 컬럼이 있는 테이블 간의 조인을 간단히 표현하는 방법

반드시 두 테이블 간의 동일한 컬럼명, 타입을 가진 컬럼이 필요

없을 경우 교차조인이 됨.

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

SELECT EMP_NAME, DEPT_TITLE
FROM EMPLOYEE
NATURAL JOIN DEPARTMENT ;
--> 잘못 조인하면 CROSS JOIN 결과 조회

7. 다중 조인

N개의 테이블을 조회할 때 사용 (순서 중요!)

사원이름, 부서명, 지역명 조회
--> EMPLOYEE, DEPARTMENT, LOCATION

-- ANSI 표준
SELECT EMP_NAME, DEPT_TITLE, LOCAL_NAME
FROM EMPLOYEE
JOIN DEPARTMENT ON(DEPT_CODE = DEPT_ID)
JOIN LOCATION ON (LOCATION_ID = LOCAL_CODE);

--> JOIN은 위에서 아래로 차례대로 진행하는데
--> 다중조인 시 앞에서 조인된 결과에 새로운 테이블 내용을 조인

SELECT *
FROM EMPLOYEE -- EMPLOYEE 테이블
JOIN DEPARTMENT ON(DEPT_CODE = DEPT_ID) 
-- EMPLOYEE 테이블 + DEPARTMENT 테이블
JOIN LOCATION ON (LOCATION_ID = LOCAL_CODE); 
-- EMPLOYEE 테이블 + DEPARTMENT 테이블 + LOCATION 테이블

-- 순서 오류!
SELECT *
FROM EMPLOYEE
JOIN LOCATION ON (LOCATION_ID = LOCAL_CODE)
JOIN DEPARTMENT ON(DEPT_CODE = DEPT_ID); 
-- SQL Error [904] [42000]: ORA-00904: "LOCATION_ID": 부적합한 식별자
--> EMPLOYEE 테이블에 LOCATION_ID 컬럼이 없어서 오류 발생
--> 해결 방법: DEPARTMENT와 LOCATION 조인 순서를 바꿔서
-- 			   EMPLOYEE와 DEPARTMENT가 조인된 결과를 먼저 만들어
--			   LOCATION_ID 컬럼이 존재할 수 있도록 만든다!

-- 오라클 전용
SELECT EMP_NAME, DEPT_TITLE, LOCAL_NAME
FROM EMPLOYEE, DEPARTMENT, LOCATION
WHERE DEPT_CODE  = DEPT_ID -- EMPLOYEE + DEPARTEMNT 조인
AND LOCATION_ID = LOCAL_CODE -- (EMPLOYEE + DEPARTEMNT) + LOCATION 조인

-- 조인 순서를 지키지 않은 경우(에러발생)

0개의 댓글