[SQL] 조인

김용준·2022년 10월 25일

SQL

목록 보기
7/17

조인

  • 두 개 이상의 테이블을 가로로 연결해서 데이터를 조회하는 것.

  • 여러 테이블에 흩어져 있는 정보중에서 사용자가 원하는 정보만 가져와서 가상의 테이블처럼 활용한다.

예를 들어, EMP테이블에 있는 사원들이 속한 부서이름을 알고 싶다. 그러나 EMP테이블에는 사원들이 속한 부서의 부서번호(DEPTNO)만 있을 뿐, 부서이름은 존재하지 않는다. 부서이름은 DEPT테이블에 존재한다. 그래서 EMP테이블과 DEPT테이블을 조인하여 원하는 데이터를 조회한다.

조인의 방법

  • 오라클 조인
SELECT A.COLUMN1, B.COLUMN2
FROM TABLE1 A ,TABLE2 B
WHERE A.COLUMN1 = B.COLUMN2;

A와 B는 각각 TABLE1과 TABLE2의 별칭이다. 조인 조건과 조회할 데이터에 사용되는 컬럼을 별칭과 함께 지정한다. TABLE1의 COLUMN1과 TABLE2의 COLUMN2가 일치하는 행을 출력한다.

  • ANSI 조인
SELECT A.COLUMN1, B.COLUMN2
FROM TABLE1 A JOIN TABLE2 B
ON A.COLUMN1 = B.COLUMN2;

ANSI 조인은 모든 RDBMS에서 사용하는 표준 조인 방법이다. 오라클 조인과 다른 점은 FROM절의 두 테이블을 콤마(,) 대신 JOIN으로 연결하고, 조인 조건을 WHERE절 대신 ON으로 표현한다.

조인이 수행될 때는 두 개 이상의 테이블이 사용된다. 둘 중 먼저 읽는 테이블을 선행 테이블, 뒤에 오는 테이블을 후행 테이블이라고 한다. 선행 테이블은 조회할 데이터가 적은 테이블로 선택하는 것이 효율적이다.

크로스 조인 (Cartesian product)

  • 조인 조건을 지정하지 않고, 두 개 이상의 테이블을 조인하는 것.

  • 조인 조건을 지정하지 않으므로 조인된 테이블의 모든 데이터를 전부 가져온다.

    • 예를 들어, A테이블과 B테이블의 행의 개수가 각각 10개, 4개라면 A테이블의 한 행당 B테이블의 모든행이 연결되어 총 40개의 행이 조회된다. 따라서 조인 작업에 참조되는 테이블의 행의 개수를 모두 곱한 값이 조회결과가 된다.
SELECT *
FROM DEPARTMENTS, LOCATIONS;
DEPARTMENTS테이블과 LOCATIONS테이블을 크로스 조인했다. DEPARTMENTS테이블의 한 행당, LOCATIONS테이블의 모든행이 연결된다. 그래서 27*23으로 621개의 행이 출력되었다.

등가 조인 (Equi Join)

  • 테이블을 연결한 후, 출력할 행을 각 테이블의 특정 열과 일치하는 데이터를 기준으로 선정한다.

  • 일반적으로 많이 사용되는 조인 방식이다.

  • 내부 조인 혹은 단순 조인이라고도 부른다.

SELECT E.FIRST_NAME, E.SALARY, E.DEPARTMENT_ID, D.DEPARTMENT_NAME
FROM EMPLOYEES E, DEPARTMENTS D
WHERE E.DEPARTMENT_ID = D.DEPARTMENT_ID
AND E.SALARY >= 10000;
EMPLOYEES 테이블과 DEPARTMENTS 테이블을 조인했다. 그리고 각 테이블의 DEPARTMENT_ID가 같고 EMPLOYEES 테이블의 SALARY가 10000이상인 행을 출력했다.

DEPARTEMENTS 테이블의 DEPARTMENT_NAME은 EMPLOYEES 테이블에 존재하지 않지만 조회가 가능한 이유는 DEPARTMENTS 테이블을 조인했기 때문이다.


SELECT E.FIRST_NAME, E.SALARY, E.DEPARTMENT_ID, D.DEPARTMENT_NAME, L.CITY
FROM EMPLOYEES E, DEPARTMENTS D, LOCATIONS L
WHERE E.DEPARTMENT_ID = D.DEPARTMENT_ID
AND D.LOCATION_ID = L.LOCATION_ID
AND E.SALARY >= 10000;

위 예제에 LOCATIONS 테이블을 추가로 조인했다. DEPARTMENTS, LOCATIONS 테이블 둘 다 LOCATION_ID 컬럼이 존재한다. 이 컬럼의 데이터가 같은 행을 출력했다. D.LOCATION_ID = L.LOCATION_ID 조건이 존재하지 않는다면 EMPLOYEES, DEPARTMENTS 테이블과 LOCATIONS 테이블이 크로스 조인된다.

비등가 조인 (Non-Equi Join)

  • 조인 조건을 지정할 때, 조인 대상 테이블의 특정 컬럼이 크거나 작은 경우의 조건으로 데이터를 조회한다.
SELECT E.FIRST_NAME, E.SALARY, G.SALARY_GRADE
FROM EMPLOYEES E, SALARY_GRADES G
WHERE G.MIN_SALARY <=  E.SALARY AND E.SALARY <= G.MAX_SALARY;

SALARY_GRADES 테이블은 MIN_SALARY와 MAX_SALARY에 따라 SALARY_GRADE가 나뉘어 진다. SALARY_GRADES 테이블과 EMPLOYEES 테이블을 조인한 후, EMPLOYEES 테이블의 SALARY가 SALARY_GRADE의 어느 등급에 속하는지 출력한다.

외부 조인 (Outer join)

  • 외부조인은 한쪽 테이블에는 데이터가 있고 다른쪽 테이블에는 데이터가 존재하지 않을 때, 데이터가 있는 쪽 테이블의 내용을 누락없이 출력하는 조인방법이다.
SELECT E.EMPLOYEE_ID, E.DEPARTMENT_ID
FROM EMPLOYEES E, DEPARTMENTS D
WHERE E.DEPARTMENT_ID = D.DEPARTMENT_ID;
우선 EMPLOYEES과 DEPARTMENTS 테이블을 등가 조인한 결과를 살펴보자.

EMPLOYEE_ID가 178인 행은 조인 결과에 포함되지 않았는데, 이는 EMPLOYEES테이블에서 EMPLOYEE_ID가 178인 행의 DEPARTMENT_ID가 NULL이기 때문이다.

이처럼 조인 기준 컬럼의 데이터가 없는 행도 강제로 출력하기 위해 외부 조인을 사용한다.


SELECT E.EMPLOYEE_ID, E.DEPARTMENT_ID
FROM EMPLOYEES E, DEPARTMENTS D
WHERE E.DEPARTMENT_ID = D.DEPARTMENT_ID (+);

NULL이 존재하지 않는 쪽(D.DEPARTMENT_ID)에 (+)를 붙여 외부 조인을 사용했다. EMPLOYEES 테이블에서 DEPARTMENT_ID가 NULL인행도 출력이된다.

자체 조인 (Self Join)

  • 하나의 테이블을 이용해서 조인을 구성한다.

  • 하나의 테이블에 안에 상위데이터, 하위데이터가 있는 경우 상위데이터와 하위데이터를 서로 연관지어서 조회할 때 자체 조인이 필요하다.

  • 하나의 테이블을 역할을 각각 나누어서 조인해야 한다.

-- 모든 직원아이디, 직원이름과 해당 직원의 관리자아이디, 관리자이름 조회한다.
SELECT EMP.EMPLOYEE_ID AS EMP_ID, EMP.FIRST_NAME AS EMP_NAME, 
       MGR.EMPLOYEE_ID AS MGR_ID, MGR.FIRST_NAME AS MGR_NAME
FROM EMPLOYEES EMP, EMPLOYEES MGR
WHERE EMP.MANAGER_ID = MGR.EMPLOYEE_ID (+)
ORDER BY EMP.EMPLOYEE_ID ASC;

EMPLOYEES 테이블을 직원정보를 담는 테이블과 매니저정보를 담는 테이블로 구분해서 자체 조인했다. EMP의 MANAGER_ID와 MGR의 EMPLOYEE_ID가 일치하는 조건으로 조인하면 각 직원의 매니저 아이디와 그 매니저의 직원 아이디가 연결된다.

그런데 EMPLOYEE_ID가 100인 직원은 매니저가 존재하지 않으므로(MANAGER_ID의 값이 NULL) 조회 결과에 포함되지 않을 것이다. 이를 해결하기 위해 MGR.EMPLOYEE_ID(+)를 추가하여 외부 조인했다.

profile
차선이 모여 최선이 된다.

0개의 댓글