/ #SQL

SQL - 조인(JOIN)

조인(JOIN)

조인은 데이터베이스에서 두 개 이상의 테이블을 관련된 컬럼을 기반으로 결합하여 하나의 테이블로 합치는 메커니즘을 의미합니다.

일반적으로 행들은 기본키(PK)와 외래키(FK)의 연관관계에 의해 조인이 성립됩니다. 하지만 PK, FK의 관계가 없더라도 논리적인 값들의 연관관계만으로도 조인이 성립할 수 있습니다.

동등 조인(Equi Join)

동등 조인은 일반적으로 “조인 키”라고 하는 일치하는 열을 기반으로 두 테이블을 결합하는 조인 작업 유형입니다.

특히 동등 조인은 조인 키가 정확히 일치하는 두 테이블의 행만 반환합니다. 즉, 조인 키 값이 두 테이블에서 동일한 두 테이블의 모든 열을 포함하는 새 테이블을 생성합니다.

예를 들어 “ORDERS”와 “EMPLOYEES”라는 두 개의 테이블이 있다고 가정합니다. 각 주문에는 “EMPLOYEES” 테이블의 직원에 해당하는 EMPLOYEE_ID가 있습니다. 모든 주문 및 관련 고객 정보를 찾으려면 두 테이블의 EMPLOYEE_ID 컬럼에서 동등 조인을 수행하면 됩니다.

아래는 예제 데이터 입니다.

EMPLOYEES
EMPLOYEE_ID FIRST_NAME LAST_NAME
1 John Smith
2 Jane Doe
3 Bob Johnson
4 Sarah Lee
ORDERS
ORDER_ID EMPLOYEE_ID ORDER_DATE
1001 1 2023-01-01
1002 2 2023-01-15
1003 3 2023-02-01
1004 4 2023-02-15

두 테이블 모두에 존재하는 EMPLOYEE_ID 컬럼을 통해 동등 조인을 수행할 수 있습니다.

동등 조인 예제
SELECT EMPLOYEES.FIRST_NAME,
       EMPLOYEES.LAST_NAME,
       ORDERS.ORDER_ID,
       TO_CHAR(ORDERS.ORDER_DATE, 'YYYY-MM-DD') ORDER_DATE
  FROM EMPLOYEES, ORDERS
 WHERE EMPLOYEES.EMPLOYEE_ID = ORDERS.EMPLOYEE_ID;

결과는 다음과 같습니다.

동등 조인 결과
LAST_NAME FIRST_NAME ORDER_ID ORDER_DATE
Smith John 1001 2023-01-01
Doe Jane 1002 2023-01-15
Johnson Bob 1003 2023-02-01
Lee Sarah 1004 2023-02-15

비동등 조인(Non Equi Join)

비동등 조인은 조인 조건이 같지 않은 비교 연산자를 기반으로 하는 SQL의 조인 유형입니다. 동등 연산자(=)가 아닌 다른 연산자를 사용하여 조인을 수행합니다.

대부분 비동등 조인을 수행할 수 있지만, 설계상의 이유로 수행이 불가능할 수도 있습니다.

아래는 예제 데이터 입니다.

CUSTOMERS
CUSTOMER_ID NAME AMOUNT
1 John 450000
2 Jane 150000
3 Bob 600000
4 Sarah 300000
GRADE
GRADE LOW HIGH
1 100000 199999
2 200000 299999
3 300000 399999
4 400000 499999
5 500000 599999
6 600000 699999

고객의 총 구매액에 대하여 등급을 구하고 싶다면 다음과 같은 비동등 조인 쿼리를 작성할 수 있습니다.

비동등 조인 예제
SELECT CUSTOMERS.NAME,
       CUSTOMERS.AMOUNT,
       GRADE.GRADE
  FROM CUSTOMERS, GRADE
 WHERE CUSTOMERS.AMOUNT BETWEEN GRADE.LOW AND GRADE.HIGH;

결과는 다음과 같습니다.

비동등 조인 결과
NAME AMOUNT GRADE
John 450000 4
Jane 150000 1
Bob 600000 6
Sarah 300000 3

표준 조인

표준 조인은 ANSI/ISO 표준에서 규정한 조인입니다.

표준 조인에는 내부 조인(Inner Join), 외부 조인(Outer Join), 크로스 조인(Cross Join), 자연 조인(Natural Join)이 있습니다.

내부 조인(Inner Join)

내부 조인은 조인 조건에서 동일한 값이 있는 행만 반환하는 조인입니다.

내부 조인 문법
SELECT 컬럼명
  FROM 테이블1
 INNER JOIN 테이블2
    ON 조건절;

다음과 같은 예제 데이터가 있다고 가정합시다.

EMPLOYEES
EMPLOYEE_ID FIRST_NAME LAST_NAME
1 John Smith
2 Jane Doe
3 Bob Johnson
4 Sarah Lee
ORDERS
ORDER_ID EMPLOYEE_ID ORDER_DATE
1001 1 2023-01-01
1002 2 2023-01-15
1003 1 2023-02-01
1004 5 2023-02-15

EMPLOYEES 테이블에 있는 직원 중 주문 이력이 있는 직원을 확인하고 싶다면 다음과 같이 쿼리를 작성하면 됩니다.

내부 조인 예제
SELECT EMPLOYEES.EMPLOYEE_ID,
       EMPLOYEES.FIRST_NAME,
       EMPLOYEES.LAST_NAME,
       TO_CHAR(ORDERS.ORDER_DATE, 'YYYY-MM-DD') ORDER_DATE
  FROM EMPLOYEES
 INNER JOIN ORDERS
    ON EMPLOYEES.EMPLOYEE_ID = ORDERS.EMPLOYEE_ID;

결과는 다음과 같습니다.

내부 조인 결과
EMPLOYEE_ID FIRST_NAME LAST_NAME ORDER_DATE
1 John Smith 2023-01-01
2 Jane Doe 2023-01-15
1 John Smith 2023-02-01

오라클의 경우 다음과 같이 내부 조인 쿼리를 작성할 수 있습니다.

오라클 내부 조인 예제
SELECT EMPLOYEES.EMPLOYEE_ID,
       EMPLOYEES.FIRST_NAME,
       EMPLOYEES.LAST_NAME,
       TO_CHAR(ORDERS.ORDER_DATE, 'YYYY-MM-DD') ORDER_DATE
  FROM EMPLOYEES, ORDERS
 WHERE EMPLOYEES.EMPLOYEE_ID = ORDERS.EMPLOYEE_ID;

외부 조인(Outer Join)

외부 조인은 조인 조건에서 동일한 값이 없더라도 행을 반환하는 조인입니다.

외부 조인은 왼쪽 테이블을 기준으로 외부 조인을 수행하는 Left Outer Join, 오른쪽 테이블을 기준으로 외부 조인을 수행하는 Right Outer Join, 양쪽 테이블을 기준으로 외부 조인을 수행하는 Full Outer Join이 있습니다.

Left Outer Join

Left Outer Join은 왼쪽 테이블을 기준으로 외부 조인을 수행합니다.

Left Outer Join 예제
SELECT EMPLOYEES.EMPLOYEE_ID,
       EMPLOYEES.FIRST_NAME,
       EMPLOYEES.LAST_NAME,
       TO_CHAR(ORDERS.ORDER_DATE, 'YYYY-MM-DD') ORDER_DATE
  FROM EMPLOYEES
  LEFT OUTER JOIN ORDERS
    ON EMPLOYEES.EMPLOYEE_ID = ORDERS.EMPLOYEE_ID;

결과는 다음과 같습니다.

Left Outer Join 결과
EMPLOYEE_ID FIRST_NAME LAST_NAME ORDER_DATE
1 John Smith 2023-01-01
2 Jane Doe 2023-01-15
1 John Smith 2023-02-01
4 Sarah Lee  
3 Bob Johnson  

오라클의 경우 다음과 같이 Left Outer Join 쿼리를 작성할 수 있습니다.

오라클 Left Outer Join 예제
SELECT EMPLOYEES.EMPLOYEE_ID,
       EMPLOYEES.FIRST_NAME,
       EMPLOYEES.LAST_NAME,
       TO_CHAR(ORDERS.ORDER_DATE, 'YYYY-MM-DD') ORDER_DATE
  FROM EMPLOYEES, ORDERS
 WHERE EMPLOYEES.EMPLOYEE_ID = ORDERS.EMPLOYEE_ID(+);

Right Outer Join

Right Outer Join은 오른쪽 테이블을 기준으로 외부 조인을 수행합니다.

Right Outer Join 예제
SELECT EMPLOYEES.EMPLOYEE_ID,
       EMPLOYEES.FIRST_NAME,
       EMPLOYEES.LAST_NAME,
       TO_CHAR(ORDERS.ORDER_DATE, 'YYYY-MM-DD') ORDER_DATE
  FROM EMPLOYEES
 RIGHT OUTER JOIN ORDERS
    ON EMPLOYEES.EMPLOYEE_ID = ORDERS.EMPLOYEE_ID;

결과는 다음과 같습니다.

Right Outer Join 결과
EMPLOYEE_ID FIRST_NAME LAST_NAME ORDER_DATE
1 John Smith 2023-01-01
1 John Smith 2023-02-01
2 Jane Doe 2023-01-15
      2023-02-15

오라클의 경우 다음과 같이 Left Outer Join 쿼리를 작성할 수 있습니다.

오라클 Right Outer Join 예제
SELECT EMPLOYEES.EMPLOYEE_ID,
       EMPLOYEES.FIRST_NAME,
       EMPLOYEES.LAST_NAME,
       TO_CHAR(ORDERS.ORDER_DATE, 'YYYY-MM-DD') ORDER_DATE
  FROM EMPLOYEES, ORDERS
 WHERE EMPLOYEES.EMPLOYEE_ID(+) = ORDERS.EMPLOYEE_ID;

Full Outer Join

Full Outer Join은 오른쪽 테이블을 기준으로 외부 조인을 수행합니다.

Full Outer Join 예제
SELECT EMPLOYEES.EMPLOYEE_ID,
       EMPLOYEES.FIRST_NAME,
       EMPLOYEES.LAST_NAME,
       TO_CHAR(ORDERS.ORDER_DATE, 'YYYY-MM-DD') ORDER_DATE
  FROM EMPLOYEES
  FULL OUTER JOIN ORDERS
    ON EMPLOYEES.EMPLOYEE_ID = ORDERS.EMPLOYEE_ID;

결과는 다음과 같습니다.

Full Outer Join 결과
EMPLOYEE_ID FIRST_NAME LAST_NAME ORDER_DATE
1 John Smith 2023-01-01
2 Jane Doe 2023-01-15
1 John Smith 2023-02-01
      2023-02-15
4 Sarah Lee  
3 Bob Johnson  

오라클의 경우 Full Outer Join 문법이 없습니다.

크로스 조인(Cross Join)

크로스 조인은 조인 조건 없이 모든 데이터의 조합을 나타내는 조인입니다.

크로스 조인 문법
SELECT 컬럼명
  FROM 테이블1
 CROSS JOIN 테이블2;
크로스 조인 예제
SELECT EMPLOYEES.EMPLOYEE_ID,
       EMPLOYEES.FIRST_NAME,
       EMPLOYEES.LAST_NAME,
       TO_CHAR(ORDERS.ORDER_DATE, 'YYYY-MM-DD') ORDER_DATE
  FROM EMPLOYEES
 CROSS JOIN ORDERS;

결과는 다음과 같습니다.

크로스 조인 결과
EMPLOYEE_ID FIRST_NAME LAST_NAME ORDER_DATE
1 John Smith 2023-01-01
1 John Smith 2023-01-15
1 John Smith 2023-02-01
1 John Smith 2023-02-15
2 Jane Doe 2023-01-01
2 Jane Doe 2023-01-15
2 Jane Doe 2023-02-01
2 Jane Doe 2023-02-15
3 Bob Johnson 2023-01-01
3 Bob Johnson 2023-01-15
3 Bob Johnson 2023-02-01
3 Bob Johnson 2023-02-15
4 Sarah Lee 2023-01-01
4 Sarah Lee 2023-01-15
4 Sarah Lee 2023-02-01
4 Sarah Lee 2023-02-15

자연 조인(Natural Join)

자연 조인은 서로 다른 테이블에서 동일한 이름을 갖는 컬럼에 대하여 자동으로 동등 조인을 수행합니다.

자연 조인 문법
 SELECT 컬럼명
   FROM 테이블1
NATURAL JOIN 테이블2;
자연 조인 예제
 SELECT EMPLOYEE_ID,
        EMPLOYEES.FIRST_NAME,
        EMPLOYEES.LAST_NAME,
        TO_CHAR(ORDERS.ORDER_DATE, 'YYYY-MM-DD') ORDER_DATE
   FROM EMPLOYEES
NATURAL JOIN ORDERS;

EMPLOYEES 테이블과 ORDERS 테이블에서 동일한 이름을 가지는 EMPLOYEE_ID 컬럼은 별명(Alias)를 주지 않았습니다. 이때 Natural Join을 사용하면 EMPLOYEE_ID 컬럼을 기준으로 내부 조인을 수행하게 됩니다.

결과는 다음과 같이 내부 조인의 결과와 같음을 확인할 수 있습니다.

자연 조인 결과
EMPLOYEE_ID FIRST_NAME LAST_NAME ORDER_DATE
1 John Smith 2023-01-01
2 Jane Doe 2023-01-15
1 John Smith 2023-02-01

내부 조인에서도 ON 조건절 대신에 USING 조건절을 사용한다면 자연 조인처럼 별명(Alias) 없이 컬럼을 지정할 수 있습니다.

USING 조건절 예제
SELECT EMPLOYEE_ID,
       EMPLOYEES.FIRST_NAME,
       EMPLOYEES.LAST_NAME,
      TO_CHAR(ORDERS.ORDER_DATE, 'YYYY-MM-DD') ORDER_DATE
  FROM EMPLOYEES
 INNER JOIN ORDERS
 USING (EMPLOYEE_ID);