TABLE JOIN

  • 두 개 이상의 테이블이나 데이터베이스를 서로 연결하여 데이터를 검색할 때 사용하는 방법
  • 서로 연관있는 테이블을 이용하여 두 개의 테이블이 마치 하나의 테이블인 것처럼 보여주는 것
  • 일반적으로 PRIMARY KEY(PK)FOREIGN KEY(FK)를 사용하여 JOIN하는 경우가 대부분이지만 논리적인 값들의 연관으로 JOIN하는 경우도 있다.

 

구문

묵시적 JOIN
SELECT table1.column1 [ , table2.column2...]
FROM table1, table2
WHERE table1.column1 = table2.column2;

 

명시적 JOIN
SELECT table1.column1 [ , table2.column2...]
FROM table1 JOIN table2
ON table1.column1 = table2.column2;

 

 

※ 참고

  • 정규화를 통해 나누어진 여러 테이블을 JOIN을 통해 질의해야 원하는 결과를 얻어올 수 있다.
  • 정규화(Normalization)란?
    정규화를 통해 하나의 테이블에 중복된 데이터가 없어야 한다는 원칙에 따라 반복적인 데이터를 분리하고, 각 데이터가 종속된 테이블에 적절히 배치되도록 작업을 수행하는 일

 

Guideline

  • 똑같은 컬럼명이 존재하는 테이블이 있을 경우는 반드시 컬럼명 앞에 테이블명을 붙인다.
  • n개의 테이블을 조인하려면 최소한 n-1번의 조인 조건문이 필요하다.

 

JOIN의 종류

종류 설명
EQUI JOIN JOIN 조건이 정확히 일치하는 경우에 사용 (pk와 fk를 사용하여)
NON-EQUI JOIN JOIN 조건이 정확히 일치하지 않는 경우에 사용 (등급, 학점)
OUTER JOIN JOIN 조건이 정확히 일치하지 않는 경우에도 모든 행들을 출력
SELF JOIN 하나의 테이블에서 행들을 JOIN하고자 할 때 사용
Cartesian Product 모든 가능한 행들의 JOIN
Set Operator 집합 연산자 - 여러 개의 SELECT 문장을 연결하여 작성

 

 


1. EQUI JOIN (INNER JOIN)

  • 조인 조건에서 '='을 사용하여 값들이 정확하게 일치하는 경우에 사용하는 JOIN을 의미한다.
  • 대부분 pk와 fk의 관계를 이용하여 조인한다.
  • 다른 말로 단순 조인 or 내부 조인이라고 한다.
테이블에서 ALIAS 사용
  • 테이블 별칭을 사용하여 긴 테이블명을 간단하게 사용한다.
  • 테이블 별칭은 30자까지 사용이 가능하지만, 짧을 수록 좋다.
  • FROM 절에서 별칭이 사용되면 SELECT문 전체에서 사용 가능하다.
  • 테이블의 별칭은 현재 SELECT문에서만 유용하다.

[묵시적 JOIN]

SELECT emp.deptno, dname, empno, ename, job
FROM dept, emp
WHERE dept.deptno = emp.deptno
ORDER BY emp.deptno asc;

 

[명시적 JOIN]

SELECT D.*, E.*
FROM dept D RIGHT OUTER JOIN emp e
ON D.deptno = E.deptno
ORDER BY D.deptno;

 

 

[실습]

-- SALESMAN의 사원번호, 이름, 급여, 부서명, 근무지를 출력하여라. (EMP, DEPT)
SELECT EMPNO, ENAME, SAL, DNAME, LOC, JOB
FROM EMP JOIN DEPT
ON EMP.DEPTNO = DEPT.DEPTNO
WHERE EMP.JOB = 'SALESMAN'
ORDER BY EMPNO;

-- 서로 연관이 있는 CATEGORY 테이블과 PRODUCTS 테이블을 이용하여
-- 각 상품별로 카테고리 이름과 상품 이름을 함께 보여주세요.
SELECT CATEGORY_CODE, CATEGORY_NAME, PRODUCTS_NAME, OUTPUT_PRICE
FROM CATEGORY C JOIN PRODUCTS P
ON c.category_code = p.category_fk
ORDER BY 1;

-- 카테고리 테이블과 상품 테이블을 조인하여 화면에 출력하되 상품의 정보 중
-- 제조업체(COMPANY)가 삼성인 상품의 정보만 추출하여 
-- 카테고리 이름과 상품이름, 상품가격, 제조사 등의 정보를 화면에 보여주세요.
SELECT CATEGORY_NAME, PRODUCTS_NAME, OUTPUT_PRICE, COMPANY
FROM CATEGORY C JOIN PRODUCTS P
ON c.category_code = p.category_fk
WHERE P.COMPANY = '삼성';

-- 각 상품별로 카테고리 및 상품명, 가격을 출력하세요. 단 카테고리가 'TV'인 것은 
-- 제외하고 나머지 정보는 상품의 가격이 저렴한 순으로 정렬하세요.
SELECT CATEGORY_NAME, PRODUCTS_NAME, OUTPUT_PRICE
FROM CATEGORY C JOIN PRODUCTS P
ON c.category_code = p.category_fk
WHERE CATEGORY_NAME <> 'TV'
ORDER BY 3;

 

 


2. NON-EQUI JOIN

  • '='가 아닌 다른 연산기호를 사용하여 조인하는 경우
  • BETWEEN ~ AND 연산자를 주로 이용한다.

SALGRADE 테이블

--사원정보를 보여주되 사번, 이름, 업무, 급여
--급여등급의 최저구간, 급여등급의 최고구간을 함께 보여주세요
SELECT EMPNO,ENAME, JOB, SAL, GRADE, LOSAL, HISAL
FROM EMP E JOIN SALGRADE S
ON E.SAL BETWEEN S.LOSAL AND S.HISAL
ORDER BY SAL DESC;

 

 


3. OUTER JOIN

  • 한쪽 테이블에 일치하는 행이 없으면 다른 쪽 테이블을 null로 하여 값을 보여준다.

1) 묵시적 JOIN

SELECT 컬럼1, 컬럼2, ...
FROM 테이블1, 테이블2
WHERE 테이블1.컬럼 = 테이블2.컬럼(+)
  • (+) 기호는 null열이 작성되는 쪽에 붙는다.
  • 이 경우 테이블1이 기준이 된다. 두 개의 테이블 가운데 기준 테이블을 중심으로 테이블1.컬럼과 테이블2.컬럼의 EQUAL조건 에서 만족하지 않는 항목이 있더라도 테이블2 항목을 null로 설정 하여 출력하게 된다.

DEPT 테이블

--DEPT, EMP 테이블을 JOIN하여라.
--[1] 40번, 50번 부서가 나오지 않음
SELECT D.*, ENAME, E.DEPTNO, SAL
FROM DEPT D, EMP E
WHERE D.DEPTNO = E.DEPTNO 
ORDER BY 1;

--[2] 40번, 50번 부서가 나옴
SELECT D.*, ENAME, E.DEPTNO, SAL
FROM DEPT D, EMP E
WHERE D.DEPTNO = E.DEPTNO(+)
ORDER BY 1;

 

 

2) 명시적 JOIN

1. LEFT OUTER JOIN ( = LEFT JOIN)

왼쪽 테이블을 기준으로 하여 출력함

왼쪽: DEPT(DEPTNO가 10~50까지 있음) / 오른쪽: EMP(DEPTNO가 10~30까지 있음)

SELECT D.DEPTNO, DNAME, ENAME, E.DEPTNO, SAL
FROM DEPT D LEFT OUTER JOIN EMP E
ON D.DEPTNO = E.DEPTNO
ORDER BY 1;

왼쪽 DEPT 테이블을 기준으로 조인했기 때문에 DEPTNO의 40, 50도 출력됨

 

2. RIGHT OUTER JOIN ( = RIGHT JOIN)

오른쪽 테이블을 기준으로 하여 출력함

SELECT D.DEPTNO, DNAME, ENAME, E.DEPTNO, SAL
FROM DEPT D RIGHT OUTER JOIN EMP E
ON D.DEPTNO = E.DEPTNO
ORDER BY 1;

 

오른쪽 EMP 테이블을 기준으로 조인했기 때문에 DEPTNO가 10, 20, 30까지만 출력됨

 

3. FULL OUTER JOIN

  • 양쪽 테이블에 다 OUTER JOIN을 하는 것
  • TWO-WAY OUTER JOIN 또는 FULL OUTER JOIN이라고도 한다.
--EMP의 DEPTNO는 10,20,30 존재 / DEPT의 DEPTNO는 10, 20, 30, 40, 50 존재
SELECT DISTINCT(E.DEPTNO), D.DEPTNO
FROM EMP E FULL OUTER JOIN DEPT D
ON E.DEPTNO = D.DEPTNO
ORDER BY 1;

 

 


4. SELF JOIN

  • 때로 하나의 테이블을 자체적으로 조인할 필요가 있다. 가령 각 사원들의 관리자 이름을 알기 위해서 자체적으로 emp테이블을 조인하는 것이 필요하다.
  • 데이터가 서로 포함 관계를 가지는 경우: 담당, 구성, 연락
--emp테이블에서 각 직원들의 정보와 직원들을 담당하는 매니저의 이름을 출력하세요.
SELECT E.*, M.ENAME AS MANAGER_NAME
FROM EMP E LEFT OUTER JOIN EMP M
ON M.EMPNO = E.MGR
ORDER BY E.EMPNO;

 


5. Cartesian Product ( = CROSS JOIN)

모든 가능한 행들의 JOIN으로 다음과 같은 경우에 발생한다.

  • 조인 조건이 생략된 경우
  • 조인 조건이 잘못된 경우
  • 첫 번째 테이블의 모든 행이 두 번째 테이블의 모든 행과 조인되는 경우
  • 결과: 양쪽 행의 개수를 곱한 개수
  • Cartesian Product는 많은 수의 행을 생성하지만, 결과는 유용하지 못하다. 불필요한 데이터가 나온다.
select * from dept; --5행
select * from emp; --14행

--조인 조건을 생략한 경우
SELECT D.DEPTNO, DNAME, E.DEPTNO, ENAME
FROM DEPT D, EMP E
ORDER BY 1, 3;
-- => DEPT의 5개 행과 x EMO의 14개 행 ==> 70개의 행이 출력됨

 

 


6. Set Operator - 집합 연산자

  • 하나 이상의 테이블로부터 자료를 검색하는 또 다른 방법은 Set(집합) 연산자를 이용하는 방법이 있다. 즉, Set 연산자를 이용하여 여러 개의 SELECT 문장을 연결하여 작성할 수 있다.
SELECT 컬럼명1, ... FROM table1
SET OPERATOR [UNION, INTERSECT, MINUS]
SELECT 컬럼명1, ... FROM table2

 

 

가이드라인

  • 첫 번째 SELECT 구문에서 기술된 컬럼과 두 번째 SELECT 구문에서 기술된 컬럼들은 좌측부터 1대 1로 대응하여 그 개수와 타입이 일치해야 한다.
  • FROM 절 뒤에 기술되는 테이블은 같을 수도 있고, 다를 수도 있다.
  • 출력되는 heading은 첫 번째 SELECT 구문에서 기술된 컬럼이 출력된다.
  • ORDER BY는 단 한 번만 기술 가능하고, SELECT 구문의 마지막에 기술한다.
  • SELECT 문장은 위에서 아래로 수행되고, 이를 변경하고자 할 경우는 괄호를 사용한다.

 

 

종류

종류 설명
UNION 각 결과의 합집합 (중복되는 값은 한 번만 출력)
UNION ALL 모든 값들의 합집합 
INTERSECT 각 결과의 중복되는 부분만 출력 (교집합)
MINUS 첫 번째 결과에서 두 번째 결과를 뺌 (차집합)

 

합집합(UNION / UNION ALL)

  • UNION: 중복되는 값은 한 번만 출력
  • UNION ALL: 모든 값들의 합집합

DEPT 테이블 / EMP 테이블

--UNION: 중복되는 값은 한번만 출력
SELECT * FROM DEPT; --DEPTNO: 10,20,30,40,50
SELECT * FROM EMP; --DEPTNO: 10,20,30
SELECT DEPTNO FROM DEPT
UNION
SELECT DEPTNO FROM EMP;

--UNION ALL: 모든 값들의 합집합
SELECT DEPTNO FROM DEPT
UNION ALL --DEPT의 5개 + EMP 14개 => 18개 행 출력
SELECT DEPTNO FROM EMP;

 

 

교집합(INTERSECT)

SELECT DEPTNO FROM DEPT --DEPTNO: 10,20,30,40,50
INTERSECT
SELECT DEPTNO FROM EMP; --DEPTNO: 10,20,30

 

 

차집합(MINUS)

SELECT DEPTNO FROM DEPT --DEPTNO: 10,20,30,40,50
MINUS
SELECT DEPTNO FROM EMP; --DEPTNO: 10,20,30

 

+ Recent posts