Database/Oracle

[Oracle] JOIN (1) 등가조인(EQUAL JOIN), 내부조인(INNER JOIN)

21종 2023. 7. 7. 12:41

    < JOIN >

    두 개 이상의 테이블에서 데이터를 조회하고자 할 때 사용되는 구문
    조회 결과는 하나의 결과물(RESULT SET)로 나옴


관계형 데이터베이스는 최소한의 데이터로 각각의 테이블에 데이터를 담고 있음 (중복을 최소화하기 위해 최대한 쪼개서 관리함)

 

EMPLOYEE TABLE
DEPARTMENT TABLE


  -- 위의 두테이블에서 어떤 사원이 어떤 부서에 속해있는지 궁금함! 코드말고.. 이름으로..
    
  => 관계형 데이터베이스에서 SQL문을 아용한 테이블간에 "관계"를 맺는 방법
        (무작정 다 조회를 해오는게 아니라 각 테이블간 연결고리로써의 데이터를 매칭해서 조회 시켜야함!!)

  JOIN 크게 "오라클 전용구문" 과 "ANSI 구문" (ANSI == 미국국립표준협회) => 아스키코드표 만드는 단체!

 

[ JOIN 용어 정리 ]

 

 

 


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

연결시키는 컬럼의 값이 일치하는 행들만 조인돼서 조회 (== 일치하는 값이 없는 행은 조회에서 제외)


-->> 오라클 전용구문

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

 

 

-- 1) 연결한 두 컬럼명이 다른 경우 (EMPLOYEE : DEPT_CODE, DEPARTMENT : DEPT_ID)

-- 사번, 사원명, 부서코드, 부서명을 같이 조회

 

EMPLOYEE TABLE

SELECT EMP_ID, EMP_NAME, DEPT_CODE
FROM EMPLOYEE;

 

DEPARTMENT TABLE

SELECT DEPT_ID, DEPT_TITLE
FROM DEPARTMENT;

 

-- 전체 사원들의 사번, 사원명, 부서코드, 부서명 조회하고자 할 때

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

-- 일치하는 값이 없는 행은 조회에서 제외된거 확인 가능
-- DEPT_CODE 가 NULL인 사원 조회 X, DEPT_ID가 D3, D4, D7 조회 X

 

 

-- 2) 연결한 두 컬럼명이 같은 경우 (EMPLOYEE : JOB_CODE, JOB : JOB_CODE)
-- 사번, 사원명, 직급코드, 직급명

 

EMPLOYEE TABLE

SELECT EMP_ID, EMP_NAME, JOB_CODE
FROM EMPLOYEE;

 

JOB TABLE

SELECT JOB_CODE, JOB_NAME
FROM JOB;

 

-- 전체 사원들의 사번, 사원명, 직급코드, 직급명 조회 하고자 할 때

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

-- ORA-00918: column ambiguously defined 오류
-- ambiguously : 애매하다. 모호하다.

 

-- 1) 해결방법1. 테이블명을 이용하는 방법

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

 

-- 2) 해결방법2. 테이블에 별칭을 부여해서 이용하는 방법

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


-->> ANSI 구문

-- FROM절에 기준이 되는 테이블을 하나 기술 한 후
-- JOIN절에 같이 조회하고자 하는 테이블 기술 + 매칭시킬 컬럼에 대한 조건도 기술
-- JOIN USING, JOIN ON

 

 

-- 1) 연결할 두 컬럼명이 다른 경우 (EMPLOYEE : DEPT_CODE, DEPARTMENT : DEPT_ID)
--  오로지 JOIN ON 구문으로만 사용 가능!!!
--  사번, 사원명, 부서코드, 부서명

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

 

-- 2) 연결할 두 컬럼명이 같은 경우 (E:JOB_CODE, J:JOB_CODE)
--  JOIN ON, JOIN USING 구문 사용 가능!
--  사번, 사원명, 직급코드, 직급명

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

-- ORA-00918: column ambiguously defined

 

 

-- 해결방법 1. 테이블명 또는 별칭을 이용해서 하는 방법

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

 

-- 해결방법 2. JOIN USING 구문 사용하는 방법 (두 컬럼명이 일치할때만 사용 가능)

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

 

-------------------------------------------------- [ 참고사항 ] --------------------------------------------------

-- 자연조인(NATURAL JOIN) : 각 테이블마다 동일한 컬럼이 한 개만 존재할 경우

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

-----------------------------------------------------------------------------------------------------------------------------

-- 추가적인 조건도 당근 제시 가능

-- 직급이 대리인 사원의 이름, 직급명, 급여 조회

 

-- >> 오라클 전용 구문

SELECT EMP_NAME, JOB_NAME, SALARY
FROM EMPLOYEE E, JOB J
WHERE E.JOB_CODE = J.JOB_CODE
AND J.JOB_NAME = '대리';

 

-->> ANSI 구문

SELECT EMP_NAME, JOB_NAME, SALARY
FROM EMPLOYEE -- 1
JOIN JOB USING(JOB_CODE) -- 2
WHERE JOB_NAME = '대리'; -- 3


실습문제

 

-- 1. 부서가 인사관리부인 사원들의 사번, 이름, 보너스 조회

SELECT * FROM EMPLOYEE;
SELECT * FROM DEPARTMENT;

EMPLOYEE TABLE
DEPARTMENT TABLE

-->> 오라클 전용 구문

SELECT EMP_ID, EMP_NAME, BONUS
FROM EMPLOYEE, DEPARTMENT
WHERE DEPT_CODE = DEPT_ID
AND DEPT_TITLE = '인사관리부';

-->> ANSI 구문

SELECT EMP_ID, EMP_NAME, BONUS
FROM EMPLOYEE
JOIN DEPARTMENT ON (DEPT_CODE = DEPT_ID)
WHERE DEPT_TITLE = '인사관리부';


-- 2. DEPARTMENT와 LOCATION을 참고해서 전체 부서의 부서코드, 부서명, 지역코드, 지역명 조회

SELECT * FROM DEPARTMENT; -- LOCATION_ID
SELECT * FROM LOCATION; -- LOCAL_CODE

DEPARTMENT TABLE
LOCATION TABLE

-->> 오라클 전용 구문

SELECT DEPT_ID, DEPT_TITLE, LOCATION_ID, LOCAL_NAME
FROM DEPARTMENT, LOCATION
WHERE LOCATION_ID = LOCAL_CODE;

-->> ANSI 구문

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


-- 3. 보너스를 받는 사원들의 사번, 사원명, 보너스, 부서명 조회

SELECT * FROM EMPLOYEE;
SELECT * FROM DEPARTMENT;

EMPLOYEE TABLE
DEPARTMENT TALBE

-->> 오라클 전용 구문

SELECT EMP_ID, EMP_NAME, BONUS, DEPT_TITLE
FROM EMPLOYEE, DEPARTMENT
WHERE DEPT_CODE = DEPT_ID
AND BONUS IS NOT NULL;

-->> ANSI 구문

SELECT EMP_ID, EMP_NAME, BONUS, DEPT_TITLE
FROM EMPLOYEE
JOIN DEPARTMENT ON (DEPT_CODE = DEPT_ID)
WHERE BONUS IS NOT NULL;


-- 4. 부서가 총무부가 아닌 사원들의 사원명, 급여, 부서명 조회

SELECT * FROM EMPLOYEE;
SELECT * FROM DEPARTMENT;

EMPLOYEE TABLE
DEPARTMENT TABLE

-->> 오라클 전용 구문

SELECT EMP_NAME, SALARY, DEPT_TITLE
FROM EMPLOYEE, DEPARTMENT
WHERE DEPT_CODE = DEPT_ID
AND DEPT_TITLE != '총무부';

-->> ANSI 구문

SELECT EMP_NAME, SALARY, DEPT_TITLE
FROM EMPLOYEE
JOIN DEPARTMENT ON (DEPT_CODE = DEPT_ID)
WHERE DEPT_TITLE != '총무부';

-- 지금 현재 DEPT_CODE가 NULL 인것은 나오고 있지 않음

 

--> LEFT JOIN 또는 RIGHT JOIN 으로 해결가능하다. 다음장에서 알아보자~~