SQL(Oracle)/SQL 수업

#21. SELECT (JOIN)

열하나요 2023. 7. 31. 12:01

지금까지는 한 테이블에서 값을 조회했었다.

그런데 여러 테이블에서 값을 조회하고자 한다면?

 

21-1. JOIN

JOIN을 이용해보자.

"오라클 전용구문"과 ANSI(미국국립표준협회) 구문"으로 나눌 수 있다.

JOIN을 이용하기 위해선 연결하고자 하는 테이블 간 '연결고리'가 되어줄 컬럼이 있어야 한다.

 

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

 

<오라클 전용 구문>

EMPLOYEE의 EMP_ID "사번", EMP_NAME "사원명", DEPT_CODE "부서코드"와

DEPARTMENT의 DEPT_ID "부서코드" 와 DEPT_TITLE "부서명"을 조회하고 싶다.

EMPLOYEE와 DEPARTMENT 사이에는 각각 부서코드인 DEPT_CODE와 DEPT_ID라는 컬럼이 존재한다면,

SELECT EMP_ID, EMP_NAME, DEPT_CODE, DEPT_ID, DEPT_TITLE
  FROM EMPLOYEE, DEPARTMENT

FROM 절에 두 클래스의 이름을 모두 써주면 된다.

하지만 이렇게 쓰면, EMPLOYEE와 DEPARTMENT 클래스의 값을 각각 곱한 것과 같은 RESULT SET이 조회된다.

 

그러므로 WHERE절로 조건을 넣어주어야 한다.

EMPLOYEE의 부서코드와 DEPARTMENT의 부서코드가 같은 경우에 각각에 맞는 데이터를 조회한다! 

즉, WHERE절에는 매칭시킬 컬럼명(연결고리)에 대한 조건을 제시해주면 된다.

SELECT EMP_ID, EMP_NAME, DEPT_CODE, DEPT_ID, DEPT_TITLE
  FROM EMPLOYEE, DEPARTMENT
 WHERE DEPT_CODE = DEPT_ID;

<ANSI 구문>

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

만약, 연결할 컬럼명이 같은 경우, 위와 동일하게 작성하면 에러가 난다. (AMBIGUOUSLY)

 

<오라클 전용 구문>

이땐 테이블명을 사용하거나,

SELECT EMP_ID, EMP_NAME, JOB.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;

<ANSI 구문>

테이블명에 별칭을 붙여 사용하거나, (ON구문)

SELECT EMP_ID, EMP_NAME, E.JOB_CODE, JOB_NAME
  FROM EMPLOYEE E
  JOIN JOB J ON (E.JOB_CODE = J.JOB_CODE);

USING구문을 사용한다.

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

위의 USING구문의 예시는 NATURAL JOIN(자연조인)으로도 가능하다.

두 개의 테이블만 제시한 상태, 운 좋게도 두 개의 테이블에 일치하는 컬럼이 유일하게 딱 한 개 존재(JOB_CODE) => 알아서 매칭돼서 조회할 수 있다.

SELECT EMP_ID, EMP_NAME, JOB_CODE, JOB_NAME
  FROM EMPLOYEE
NATURAL
  JOIN JOB;

 

그런데 EQUAL JOIN / INNER JOIN은 일치하지 않는 행들은 애초에 조회되지 않는다. (NULL값이 조회되지 않음)

JOIN시 일치하지 않는 행도 포함시켜서 조회하고자 한다면,

 

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

반드시 LEFT / RIGHT를 지정해줘야 한다.

LEFT면 두 테이블 중 왼편에 기술된 테이블을 기준으로 JOIN되어 일치하는 것을 찾지 못하더라도 모두 조회되게 한다.

오라클 구문에서는 (+)표시가 있는 반대쪽이 기준이 된다.

 

<오라클 전용 구문>

SELECT EMP_NAME, SALARY, DEPT_TITLE
  FROM EMPLOYEE, DEPARTMENT
 WHERE DEPT_CODE = DEPT_ID(+);

< ANSI 구문>

SELECT EMP_NAME, SALARY, DEPT_TITLE
  FROM EMPLOYEE
  LEFT OUTER JOIN DEPARTMENT ON(DEPT_CODE = DEPT_ID);

OUTER는 생략가능.

 

만약, 두 테이블이 가진 모든 행을 조회하고자 한다면,

ANSI구문만 사용 가능하다.

<ANSI 구문>

SELECT EMP_NAME, SALARY, DEPT_TITLE
  FROM EMPLOYEE
  FULL OUTER JOIN DEPARTMENT ON(DEPT_CODE = DEPT_ID);

 

3. 카테시안 곱(CARTESIAN PRODUCT) / 교차조인(CROSS JOIN)

맨 앞에 했던 것과 같다. 방대한 데이터가 출력되기 때문에 과부하의 위험이 있다.

 

<오라클 전용 구문>

SELECT EMP_NAME, DEPT_TITLE
  FROM EMPLOYEE, DEPARTMENT;

<ANSI 구문>

SELECT EMP_NAME, DEPT_TITLE
  FROM EMPLOYEE
 CROSS JOIN DEPARTMENT;

 

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

'='이 아닌 '범위'에 포함되는 경우 매칭하는 것.

 

<오라클 전용 구문>

SELECT EMP_NAME, SALARY, SAL_GRADE.SAL_LEVEL
  FROM EMPLOYEE, SAL_GRADE
 WHERE MIN_SAL <= SALARY AND SALARY <= MAX_SAL;

<ANSI 구문>

SELECT EMP_NAME, SALARY, SAL_GRADE.SAL_LEVEL
  FROM EMPLOYEE
  JOIN SAL_GRADE ON(SALARY BETWEEN MIN_SAL AND MAX_SAL);

 

5. 자체조인(SELF JOIN)

자기 자신의 테이블과 조인을 맺는 경우

 

<오라클 전용 구문>

SELECT E.EMP_ID "사원 사번", E.EMP_NAME "사원명", E.SALARY "사원 급여",
       M.EMP_ID "사수 사번", M.EMP_NAME "사수명", M.SALARY "사수 급여"
  FROM EMPLOYEE E, EMPLOYEE M
 WHERE E.MANAGER_ID = M.EMP_ID(+);

<ANSI 구문>

SELECT E.EMP_ID "사원 사번", E.EMP_NAME "사원명", E.SALARY "사원 급여",
       M.EMP_ID "사수 사번", M.EMP_NAME "사수명", M.SALARY "사수 급여"
  FROM EMPLOYEE E
  LEFT JOIN EMPLOYEE M ON (E.MANAGER_ID = M.EMP_ID);

 

 

20-2. 다중 JOIN

두 테이블만 연결하는 게 아니라 다중으로 연결해 조회할 경우!

 

<오라클 전용 구문>

SELECT EMP_ID "사번", EMP_NAME "사원명", DEPT_TITLE "부서명", JOB_NAME "직급명", LOCAL_NAME "근무지역명"
  FROM EMPLOYEE
  LEFT JOIN DEPARTMENT ON (DEPT_CODE = DEPT_ID)
  LEFT JOIN LOCATION ON (LOCAL_CODE = LOCATION_ID)
  LEFT JOIN JOB USING(JOB_CODE);

<ANSI 구문>

SELECT EMP_ID "사번", EMP_NAME "사원명", DEPT_TITLE "부서명", JOB_NAME "직급", LOCAL_NAME "근무지역명"
  FROM EMPLOYEE E, DEPARTMENT, JOB J, LACATION
 WHERE DEPT_CODE = DEPT_ID(+)
   AND LOCATION_ID = LOCAL_CODE(+)
   AND E.KOB_CODE = J.JOB_CODE;

 

예제를 많이 풀어보자!!!

'SQL(Oracle) > SQL 수업' 카테고리의 다른 글

#23. DML, DDL, DCL, TCL, OBJECT(VIEW)  (0) 2023.08.02
#22. DDL(CREATE)  (0) 2023.08.01
#20. SQL(SELECT)  (0) 2023.07.28
#19. 세번째 시험... +과제  (0) 2023.07.27
#18. Oracle시작. SQL문  (0) 2023.07.26