하나 이상의 테이블에서 데이터를 조회하기 위해 사용하고 수행 결과는 하나의 Result Set으로 나옴
SELECT EMP_ID,
EMP_NAME,
DEPT_CODE
FROM EMPLOYEE;
SELECT DEPT_ID,
DEPT_TITLE
FROM DEPARTMENT;
오라클 | SQL : 1999표준(ANSI) |
---|---|
등가 조인 | 내부 조인(INNER JOIN), JOIN USING / ON + 자연 조인(NATURAL JOIN, 등가 조인 방법 중 하나) |
포괄 조인 | 왼쪽 외부 조인(LEFT OUTER), 오른쪽 외부 조인(RIGHT OUTER) + 전체 외부 조인(FULL OUTER, 오라클 구문으로는 사용 못함) |
자체 조인, 비등가 조인 | JOIN ON |
카테시안(카티션) 곱 (CARTESIAN PRODUCT) | 교차 조인(CROSS 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
연결되는 컬럼의 값이 일치하는 행들만 조인됨. (== 일치하는 값이 없는 행은 조인에서 제외됨.
작성 방법 크게 ANSI구문과 오라클 구문 으로 나뉘고, ANSI에서USING
과 ON
을 쓰는 방법으로 나뉜다.
ANSI는 미국 국립 표준 협회를 뜻함, 미국의 산업표준을 제정하는 민간단체로 국제표준화기구 ISO에 가입되어있다.
ANSI에서 제정된 표준을 ANSI라고 하고 여기서 제정한 표준 중 가장 유명한 것이 ASCII코드이다.
FROM
절에 쉼표(,
) 로 구분하여 합치게 될 테이블명을 기술하고
WHERE
절에 합치기에 사용할 컬럼명을 명시한다
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;
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;
연결에 사용된 컬럼의 값이 일치하지 않으면 조회 결과에 포함되지 않음 ❗
두 테이블의 지정하는 컬럼값이 일치하지 않는 행도 조인에 포함을 시킴
반드시 OUTER JOIN
임을 명시해야 한다.
SELECT EMP_NAME, DEPT_TITLE
FROM EMPLOYEE
/*INNER*/ JOIN DEPARTMENT ON (DEPT_CODE = DEPT_ID);
합치기에 사용한 두 테이블 중 왼편에 기술된 테이블의 컬럼 수를 기준으로 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(+);
합치기에 사용한 두 테이블 중 오른편에 기술된 테이블의 컬럼 수를 기준으로 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;
합치기에 사용한 두 테이블이 가진 모든 행을 결과에 포함
오라클 구문은 FULL OUTER JOIN
을 사용 못함
-- ANSI 표준
SELECT EMP_NAME, DEPT_TITLE
FROM EMPLOYEE
FULL JOIN DEPARTMENT ON(DEPT_CODE = DEPT_ID);
-- 오라클(X) : 오라클엔 FULL JOIN 구문이 없음
잘 쓰이진 않는다고 함
조인되는 테이블의 각 행들이 모두 매핑된 데이터가 검색되는 방법(곱집합)
JOIN
구문을 잘못 작성하는 경우 CROSS JOIN
의 결과가 조회됨
SELECT EMP_NAME, DEPT_TITLE
FROM EMPLOYEE
CROSS JOIN DEPARTMENT; -- 207행 == (EMPLOYEE) 23행 * (DEPARTMENT) 9행 = 270행
잘 쓰이진 않는다고 함
=
(등호)를 사용하지 않는 조인문
지정한 컬럼 값이 일치하는 경우가 아닌, 값의 범위에 포함되는 행들을 연결하는 방식
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만원 이상 받는 사람이 무슨 등급인지 조회할 때 사용
같은 테이블을 조인.
자기 자신과 조인을 맺음
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(+);
동일한 타입과 이름을 가진 컬럼이 있는 테이블 간의 조인을 간단히 표현하는 방법
반드시 두 테이블 간의 동일한 컬럼명, 타입을 가진 컬럼이 필요
없을 경우 교차조인
이 됨.
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 결과 조회
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 조인
-- 조인 순서를 지키지 않은 경우(에러발생)