- 두 개 이상의 테이블에서 함께 데이터를 조회하고자 할 때 사용되는 구문
- 조회 결과는 하나의 결과물(RESULT SET)으로 반환
JOIN은 "오라클 전용구문" , ANSI 표준구문으로 나뉜다.
- 관계형 데이터베이스에서는 데이터의 중복을 피하기 위해
- 최소한의 데이터만 각 테이블에 보관을 하고 있다
EX) 사원정보는EMPLOYEE, 부서정보는 DEPARTMENT, 직급정보는 JOB등...- 따라서 내가 사원의 정보와 부서의 정보를 하나의 결과 값으로 보기 위해서는
- 여러개의 테이블을 관계가 있는 칼럼을 통해 JOIN문을 사용하여 조회
-- JOIN을 사용 하지 않는 경우
--전체 사원들의 사번, 사원명, 부서코드, 부서명까지 알아내야 한다면?
SELECT EMP_ID, EMP_NAME, DEPT_CODE
FROM EMPLOYEE;
SELECT DEPT_ID, DEPT_TITLE
FROM DEPARTMENT;
- 연결시키고자 하는 칼럼의 값이 서로 일치 하는 행들만 조인
- 조인시 동등비교연사자를 사용하여 조인 조건을 제시
[표현법]
등가조인 (오라클)
SELECT 칼럼명들
FROM 조인 테이블명들 나열
WHERE 연결 할 칼럼에 대한 조건을 제시(=)
내부조인(ANSI 구문)
SELECT 칼럼명들
FROM 기준 삼을 테이블 1개만 제시
JOIN 위 테이블과 연걸 할 테이블 1개만 제시
1.ON (연결 할 칼럼에 대한 조건 제시(=))
2.USING (연결 할 칼럼 1개만 제시) 단 , 연결 할 칼럼의 칼럼명이 100% 동일해야 한다.
- FROM 절에 조회할 테이블들을 나열,
- WHERE절에 조인에 대한 조건을 제시
-- 전체 사원들의 사번 이름 부서코드 부서명을 알아내고자 한다.
SELECT EMP_ID, EMP_NAME, DEPT_CODE, DEPT_ID, DEPT_TITLE
FROM EMPLOYEE, DEPARTMENT --카데시안의 곱 방식
ORDER BY EMP_ID; --정렬을 통해 확인 결과 모든 행의 결과값을 반환
--등가조인 방식
SELECT EMP_ID, EMP_NAME, DEPT_CODE, DEPT_ID, DEPT_TITLE
FROM EMPLOYEE, DEPARTMENT
WHERE DEPT_CODE = DEPT_ID; --NULL 값은 제외되고 출력
-- 전체 사원들의 사번, 사원명, 직급코드, 직급명
SELECT EMP_ID, EMP_NAME, JOB_CODE, JOB_NAME
FROM EMPLOYEE, JOB
WHERE JOB_CODE = JOB_CODE;
-- 에러) COLUMN AMBIGUOUSIY SPECIFIED -> 컬럼명이 애매하다.
--즉, JOB_CODE와 같이 EMPLOYEE와 JOB에 모두 존재하는 칼럼명일 경우
--어떤 테이블의 JOB_CODE 인지 분명한 정의가 필요
--해결방법1) 테이블에 별칭 부여
SELECT EMP_ID, EMP_NAME, E.JOB_CODE, JOB_NAME
FROM EMPLOYEE "E" , JOB "J" --AS키워드 사용 불가 "" 는 사용 가능
WHERE E.JOB_CODE = J.JOB_CODE;
--해결방법2) 테이블명을 컬럼앞에 붙여주기
SELECT EMP_ID, EMP_NAME, EMPLOYEE.JOB_CODE, JOB_NAME
FROM EMPLOYEE, JOB
WHERE EMPLOYEE.JOB_CODE = JOB.JOB_CODE;
- FROM절 뒤에 테이블 "한개만" 기술
- 그뒤에 JOIN절을 붙여서 조회 하고자 하는 테이블을 기술, 매칭할 칼럼에 대한 조건으도 함께 기술
- 칼럼에 대한 조건을 제시시 ON구문 / USING 구문 2개가 존재
-- 전체 사원들의 사번, 이름, 부서코드, 부서명 알아내기
--ON구문
SELECT EMP_ID, EMP_NAME, DEPT_CODE, DEPT_TITLE
FROM EMPLOYEE
/* INNER */JOIN DEPARTMENT ON (DEPT_ID = DEPT_CODE) ;
-- USING
SELECT EMP_ID, EMP_NAME, DEPT_CODE, DEPT_TITLE
FROM EMPLOYEE
JOIN DEPARTMENT USING ( DEPT_CODE ) ;
-- USING구문은 조인할 두테이블이 동일한 칼럼명을 가지고 있을때만 사용 가능
-- 사번, 사원명, 직급코드 , 직급명 -> USING 구문 사용가능.
--1) ON 구문
SELECT EMP_ID, EMP_NAME, E.JOB_CODE, JOB_NAME
FROM EMPLOYEE E
JOIN JOB J ON (E.JOB_CODE = J.JOB_CODE);
--2) USING 구문 : 조인할 테이블 간의 칼럼명이 동일한 경우 사용이 가능
-- 이름이 동일한 칼럼명을 작성하면 해당 칼럼을 기준으로 행을 매칭
SELECT EMP_ID, EMP_NAME, JOB_CODE, JOB_NAME
FROM EMPLOYEE
JOIN JOB USING(JOB_CODE); -- USING에 사용된 칼럼은 RESULT SET에서 하나의 칼럼으로 통합
--자연조인(NATURAL JOIN) : 등가조인의 방법 중 하나
--=> 두 테이블을 JOIN 할 때 "동일한 타입과 이름"을 가진 칼럼을 조인 조건으로 사용하는 JOIN문
SELECT EMP_ID, EMP_NAME, JOB_CODE, JOB_NAME
FROM EMPLOYEE
NATURAL JOIN JOB; -- 조인에 대한 조건을 제시하지 않았다.
-- 조인시 추가적인 조건 제시하기.
-- 직급이 대리인 사원들의 정보를 조회 ( 사번, 사원명, 월급, 직급명)
-- 오라클 전용 구문
SELECT EMP_ID, EMP_NAME, SALARY,JOB_NAME
FROM EMPLOYEE E, JOB J
WHERE E.JOB_CODE = J.JOB_CODE
AND JOB_NAME = '대리';
-- ANSI구문
SELECT EMP_ID, EMP_NAME, SALARY,JOB_NAME
FROM EMPLOYEE
JOIN JOB USING(JOB_CODE)
WHERE JOB_NAME = '대리';
SELECT EMP_ID, EMP_NAME, SALARY, JOB_NAME
FROM EMPLOYEE
JOIN JOB ON (EMPLOYEE.JOB_CODE = JOB.JOB_CODE
AND JOB_NAME = '대리');
1. 부서가 '인사관리부' 인 사원들의 사번 사원명 보너스를 조회 (오라클/ ANSI구문으로 나눠서)
--오라클
SELECT EMP_ID, EMP_NAME,DEPT_CODE, BONUS
FROM EMPLOYEE E, DEPARTMENT D
WHERE E.DEPT_CODE = D.DEPT_ID
AND DEPT_TITLE = '인사관리부';
--ANSI구문
SELECT EMP_ID, EMP_NAME,DEPT_CODE, BONUS
FROM EMPLOYEE
JOIN DEPARTMENT ON DEPT_ID = DEPT_CODE --AND DEPT_TITLE = '인사관리부';
WHERE DEPT_TITLE = '인사관리부';
--2. 부서가 '총무부'가 아닌 사원들의 사원명 급여 입사일을 조회 (오라클/ ANSI구문으로 나눠서)
--오라클
SELECT EMP_NAME,DEPT_CODE, SALARY, HIRE_DATE
FROM EMPLOYEE , DEPARTMENT
WHERE DEPT_CODE = DEPT_ID
AND DEPT_TITLE != '총무부';
--ANSI구문
SELECT EMP_NAME,DEPT_CODE, SALARY, HIRE_DATE
FROM EMPLOYEE
JOIN DEPARTMENT ON DEPT_CODE = DEPT_ID
WHERE DEPT_TITLE != '총무부';
--3. 보너스를 받는 사월들의 사번 사원명 보너스 부서명을 조회 (오라클/ ANSI구문으로 나눠서)
--오라클
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. 아래의 두 테이블을 참고하여 부서코드 부서명 지역코드 국가명을 조회 (오라클/ ANSI구문으로 나눠서)
--오라클
SELECT * FROM DEPARTMENT;
SELECT* FROM NATION;
SELECT DEPT_ID, DEPT_TITLE, LOCATION_ID, NATIONAL_NAME
FROM DEPARTMENT, LOCATION L, NATION N
WHERE LOCATION_ID = LOCAL_CODE
AND L.NATIONAL_CODE = N.NATIONAL_CODE;
--ANSI구문
SELECT DEPT_ID, DEPT_TITLE, LOCATION_ID, NATIONAL_NAME
FROM DEPARTMENT
JOIN LOCATION ON LOCATION_ID = LOCAL_CODE
JOIN NATION USING(NATIONAL_CODE);
-- 전체 사원들의 사원명 급여 부서명
SELECT EMP_NAME, SALARY, DEPT_CODE, DEPT_ID, DEPT_TITLE
FROM EMPLOYEE, DEPARTMENT
WHERE DEPT_CODE = DEPT_ID; --DEPT_CODE NULL인 사원은 제외되어 출력
- 테이블간의 JOIN시 "일치하지 않는 행도" 포함시켜서 조회.
- 단, 반드시 LEFT/RIGHT를 지정해 줘야 한다.
-- 전체 사원의 사번 급여 부서명
-- 1) LEFR OUTER JOIN : 두개의 테이블 중 왼편에 기술된 테이블을 기준으로 JOIN을 한다.
-- , 왼편에 기술된 테이블의 행은 JOIN조건을 만족하지 못하더라도 항상 데이터를 조회한다.
SELECT EMP_NAME, SALARY, DEPT_TITLE
FROM EMPLOYEE, DEPARTMENT
WHERE DEPT_CODE = DEPT_ID(+);
--EMPLOYEE 테이블의 행은 왼쪽의 JOIN조건을 만족하지 못하더라고 항상 조회
-- ANSI 구문
SELECT EMP_NAME, SALARY, DEPT_TITLE
FROM EMPLOYEE
LEFT /*OUTER*/ JOIN DEPARTMENT ON DEPT_CODE = DEPT_ID; --OUTER 생략가능
-- EMPLOYEE 테이블을 기준으로 조회, EMPLOYEE에 존재하는 데이터는 모두 조회
-- 2) REGHT OUTER JOIN : 두 테이블 중 오른쪽에 기술된 테이블을 기준으로 데이터 JOIN.
SELECT EMP_NAME, SALARY, DEPT_TITLE
FROM EMPLOYEE, DEPARTMENT
WHERE DEPT_CODE(+) = DEPT_ID ;
-- ANSI
SELECT EMP_NAME, SALARY, DEPT_TITLE
FROM EMPLOYEE
RIGHT /*OUTER*/ JOIN DEPARTMENT ON DEPT_CODE = DEPT_ID;
-- 3) FULL OUTER JOIN : 두 테이블이 가진 모든 행을 조회
-- INNER 해당하는 행들 + LEFT OUTER 해당하는 행 + RIGHT OUTER행을 모두 조회
-- ANSI 구문
SELECT EMP_NAME, SALARY, DEPT_TITLE
FROM EMPLOYEE
FULL /* OUTER JOIN */ DEPARTMENT ON DEPT_CODE = DEPT_ID ;
-- 오라클 전용구문은 문법상 FULL OUTER JOIN이 불가하다.
- 모든 테이블의 각 행들이 서로 매핑된 데이터가 조회된다(곱집합)
- 두 테이블의 행들이 모두 곱해진 행들의 조합이 출력
ex) A테이블에 N개의 행 B테이블에 M개의 행이 존재할 경우 결과 행의 집합의 수는 N*M행 즉 모든 경우희 수를 조회,방대한 데이터 출력, 성능이 느려 질 수 있다.--사원명, 부서명 --사원 테이블 (24개의 행) --부서 테이블 (9개의 행이 있다) SELECT EMP_NAME, DEPT_TITLE FROM EMPLOYEE, DEPARTMENT; -- ANSI SELECT EMP_NAME, DEPT_TITLE FROM EMPLOYEE CROSS JOIN DEPARTMENT;
- '=' 를 사용하지 않는 JOIN문, 다른 비교 연사자를 써서 JOIN함(>, < >=, <=, BETWEEN 등)
- => 지정한 칼럼 값들이 일치하는 경우가 아니라 일치하는 "범위"에 포함되는 경우 매칭해서 조회
-- 사원명 급여
SELECT EMP_NAME, SALARY
FROM EMPLOYEE;
SELECT *
FROM SAL_GRADE; --단순 조회
-- 사원명, 급여, 급여등급(SAL_LEVER)
-- 오라클 전용 구문
SELECT EMP_NAME, SALARY, SAL_GRADE.SAL_LEVEL
FROM EMPLOYEE, SAL_GRADE
--WHERE SALARY >= MIN_SAL AND SALARY <= MAX_SAL;
WHERE SALARY BETWEEN MIN_SAL AND MAX_SAL;
-- ANSI 구문
SELECT EMP_NAME, SALARY, SAL_GRADE.SAL_LEVEL
FROM EMPLOYEE
JOIN SAL_GRADE ON (SALARY BETWEEN MIN_SAL AND MAX_SAL);
- 같은 테이블 JOIN시 사용.
- 자체조인의 경우 조회하고자 하는 칼럼명이 반드시 겹치기 때문에 항상 별칭 부여 필요
SELECT * FROM EMPLOYEE E; -- 모든 사원에 대한 정보 SELECT * FROM EMPLOYEE M; -- 사수에 대한 정보를 도출하기 위한 테이블
-- 사원의 사번, 사원명, 사수의 사번, 사수명
-- 오라클 전용 구문
SELECT
E.EMP_ID,
E.EMP_NAME,
E.MANAGER_ID,
M.EMP_NAME
FROM EMPLOYEE E, EMPLOYEE M
WHERE E.MANAGER_ID = M.EMP_ID(+) ;
-- ANSI 구문
SELECT
E.EMP_ID,
E.EMP_NAME,
E.MANAGER_ID,
M.EMP_NAME
FROM EMPLOYEE E
LEFT JOIN EMPLOYEE M ON (M.EMP_ID = E.MANAGER_ID);
- 3개 이상의 테이블을 조인 할때 부르는 명칭
-- 사번, 사원명, 부서명, 직급명
--오라클 전용 구문
SELECT EMP_ID,
EMP_NAME,
DEPT_TITLE,
JOB_NAME
FROM EMPLOYEE, DEPARTMENT, JOB
WHERE DEPT_CODE = DEPT_ID
AND EMPLOYEE.JOB_CODE = JOB.JOB_CODE;
-- ANSI 구문
SELECT EMP_ID,
EMP_NAME,
DEPT_TITLE,
JOB_NAME
FROM EMPLOYEE
JOIN DEPARTMENT ON DEPT_ID =DEPT_CODE
JOIN JOB USING(JOB_CODE); --2개이상일때 USING 사용이 제한된다