데이터베이스에서 데이터는 다수의 테이블에 나뉘어 저장되어 있습니다. 데이터의 중복을 제거하고 무결성을 보장하기 위해서 데이터 성격에 따라 분류하여 테이블에 저장을 하는 겁니다.
  이렇게 테이블별로 분리되어 있는 데이터를 연결하여 하나의 결과 데이터 셋으로 출력해야 할 때가 반드시 존재합니다. 이럴때 사용하는 것이 조인(Join)입니다. 

  기본적인 조인문 사용 방법은 아래와 같습니다.

ANSI-SQL ORACLE SQL
SELECT e.LAST_NAME 
          , d.DEPARTMENT_NAME 
  FROM EMPLOYEES e  
   JOIN DEPARTMENTS d 
      ON e.DEPARTMENT_ID = d.DEPARTMENT_ID 
;
SELECT e.LAST_NAME
          , d.DEPARTMENT_NAME
  FROM EMPLOYEES e
          , DEPARTMENTS d
 WHERE e.DEPARTMENT_ID = d.DEPARTMENT_ID
;

  위 예제에서는 EMPLOYEES 테이블과 DEPARTMENTS 테이블을 조인하고 있습니다. 여기서 조인 조건은 양쪽 테이블의 조인 키 컬럼인 DEPARTMENT_ID 컬럼 값이 동일한 경우이며, EMPLOYEES 테이블의 LAST_NAME 컬럼과 DEPARTMENTS 테이블의 DEPARTMENT_NAME 컬럼의 값이 결과로 출력됩니다.

  위 예제와 같이 두 개의 테이블을 조인하기 위해서는 각 테이블에 조인 키로 사용 할 수 있는 컬럼이 존재해야 합니다. 두 테이블 간의 연결고리인 조인 키 컬럼을 사용해 테이블 내 각 데이터들의 짝꿍을 찾아갈 수 있게 됩니다.
  ( 물론 조인 조건절을 생략하여 한 로우와 상대쪽 테이블의 모든 로우를 매핑시키는 Cartesian join도 존재합니다. 하지만 이 포스트에서는 기본 조인 조건인 등호 기호(=)를 이용한 동등 조인(equi-join)을 기준으로 설명하겠습니다. )

  그런데 이 조인 키 컬럼의 값이 양 쪽 테이블에 모두 존재하는 것이 아니라 한쪽 테이블에만 존재하는 경우(짝꿍이 없는 경우)가 발생할 수 있습니다.
  '상품' 테이블과 '고객주문상품' 테이블을 예로 들어보겠습니다.
  신규 상품인 망고(상품ID : 4)가 '상품' 테이블에 입력되었습니다. 하지만 신규 상품인 망고의 고객 주문이 발생하지 않는다면, '고객주문상품' 테이블에는 망고의 상품ID 값 '4'가 존재할 수 없습니다. 상품ID '4'는 오직 '상품' 테이블에만 존재하게 됩니다.

  이런 경우에 짝궁이 없는 데이터를 출력 결과에 포함할 수도 있고 제외할 수도 있습니다. 
  바꿔서 말하면 우리가 어떤 조인 종류를 선택함에 출력 결과가 달라질 수 있습니다. 

  우리가 수학시간에 배웠던 집합의 종류를 생각해보면 이해가 더 쉬워질 수 있습니다.
  데이터 집합 A와 B가 존재하는 경우, 결과 데이터 집합은 다양한 집합 연산으로 추출할 수 있습니다. 전체 데이터 집합을 추출하기 위해 합집합( A ∪ B ) 연산을 할 수 있고요. 공통인 데이터 집합을 추출하기 위해 교집합( A ∩ B ) 연산을 할 수도 있습니다. 이렇듯 집합 연산에 따라 결과 데이터 집합은 달라지게 됩니다.

  그럼, 조인 종류(Join Type)에 대해 자세히 살펴보겠습니다. 대표적인 조인 종류는 아래와 같이 4가지가 존재합니다.

1. Inner join

  Inner join은 교집합( A ∩ B ) 연산과 같습니다. 조인 키 컬럼 값이 양쪽 테이블 데이터 집합에서 공통적으로 존재하는 데이터만 조인해서 결과 데이터 집합으로 추출하게 됩니다.

  Inner join 구문은 아래와 같습니다.

ANSI-SQL ORACLE SQL
SELECT 컬럼명 [, 컬럼명]
  FROM 테이블A  
[INNER] JOIN 테이블B 
    ON 테이블A.조인키컬럼 = 테이블B.조인키컬럼
;
SELECT 컬럼명 [, 컬럼명]
  FROM 테이블A 
           , 테이블B
 WHERE 테이블A.조인키컬럼 = 테이블B.조인키컬럼
;

  위 ANSI-SQL 구문에서 'INNER' 키워드는 생략이 가능합니다. 우리가 일반적으로 사용하는 조인문( 'JOIN' 키워드만 사용하는 구문)이 바로 Inner join 구문입니다.

 

  아래는 조인 종류를 설명할 예제 데이터입니다. 

[예제 1] 상품과 고객주문상품 테이블 데이터

  고객주문상품 테이블의 상품ID가 '5'인 데이터는 부모 테이블인 상품 테이블에 존재하지 않는 값으로 FK 위반입니다. 하지만, OUTER JOIN의 예를 설명하기 위한 억지스러운 설정일 뿐입니다. 무결성에 위배되는 데이터지만 설명을 위해 이해 부탁드립니다.

  위 [예제 1] 상품 테이블과 고객주문상품 테이블을 Inner join하는 예제를 살펴보겠습니다.

-- ANSI-SQL
SQL> SELECT p.상품ID, p.상품명, o.상품ID, o.고객ID, o.주문일자, o.주문수량
    2>   FROM 상품 p
    3>    JOIN 고객주문상품 o
    4>        ON p.상품ID = o.상품ID;

 

  Inner join의 결과는 아래와 같습니다.

  상품 테이블과 고객주문상품에서 조인 키 컬럼 값이 모두 존재하는 데이터만 출력된 것을 확인하실 수 있습니다.

 

 

2. Left outer join

  Left outer join은 교집합 연산 결과와 차집합 연산 결과를 합친 것( (A  B) (A - B) )과 같습니다.
  조인 키 컬럼 값이 양쪽 테이블 데이터 집합에서 공통적으로 존재하는 데이터와 
Left outer join 키워드 왼쪽에 명시된 테이블에만 존재하는 데이터를 결과 데이터 집합으로 추출하게 됩니다.

  Left outer join 구문은 아래와 같습니다.

ANSI-SQL ORACLE SQL
SELECT 컬럼명 [, 컬럼명]
  FROM 테이블A  
   LEFT OUTER JOIN 테이블B 
      ON 테이블A.조인키컬럼 = 테이블B.조인키컬럼
;
SELECT 컬럼명 [, 컬럼명]
  FROM 테이블A 
            , 테이블B
 WHERE 테이블A.조인키컬럼 = 테이블B.조인키컬럼(+)
;

  ANSI-SQL 구문에서는 FROM 절에 조인하고자 하는 두 테이블명 사이에 'LEFT OUTER JOIN' 키워드를 입력합니다.
  ORACLE에서는 WHERE 절에서 오른쪽 테이블의 조인 키 컬럼명 뒤에 '(+)' 기호를 입력해줍니다.

  위 [예제 1] 상품 테이블과 고객주문상품 테이블을 Left outer join 하는 예제를 살펴보겠습니다.

-- ANSI-SQL
SQL> SELECT p.상품ID, p.상품명, o.상품ID, o.고객ID, o.주문일자, o.주문수량
    2>    FROM 상품 p
    3>     LEFT OUTER JOIN 고객주문상품 o
    4>        ON p.상품ID = o.상품ID;

   조인하고자 하는 테이블명을 LEFT OUTER JOIN 키워드를 기준으로 양쪽에 입력하고, 조인 조건은 ON 키워드 다음에 작성해줍니다.

-- ORACLE SQL
SQL> SELECT p.상품ID, p.상품명, o.상품ID, o.고객ID, o.주문일자, o.주문수량
    2>   FROM 상품 p
    3>             , 고객주문상품 o
    4>  WHERE p.상품ID = o.상품ID(+);

  Oracle에서는 FROM 키워드 이후에 조인할 테이블명을 콤마(,)로 구분하여 나열해주고, WHERE절에 조인 조건을 작성하되, 오른쪽 테이블의 조인 키 컬럼명 뒤에 '(+)' 기호를 추가로 입력해줍니다.

  Left outer join의 결과는 아래와 같습니다.

  상품 테이블과 고객주문상품에서 조인 키 컬럼 값이 모두 존재하는 데이터와 왼쪽에 명시되었던 테이블의 상품 테이블에만 존재하는 데이터(상품ID가 4인 데이터)가 출력된 것을 확인하실 수 있습니다.
  왼쪽 상품 테이블에만 데이터가 존재하는 로우의 오른쪽 고객주문상품 테이블 컬럼 값은 NULL로 표시됩니다.

 

 

3. Right outer join

 Right outer join도 교집합 연산 결과와 차집합 연산 결과를 합친 것( (A  B)  (A - B) )과 같습니다. 차집합의 기준 집합이 Left outer join과 반대일 뿐입니다.
  아무튼 조인 키 컬럼 값이 양쪽 테이블 데이터 집합에서 공통적으로 존재하는 데이터와 
Right outer join 키워드 오른쪽에 명시된 테이블에만 존재하는 데이터를 결과 데이터 집합으로 추출하게 됩니다.

  Right outer join 구문은 아래와 같습니다.

ANSI-SQL ORACLE SQL
SELECT 컬럼명 [, 컬럼명]
  FROM 테이블A  
RIGHT OUTER JOIN 테이블B 
      ON 테이블A.조인키컬럼 = 테이블B.조인키컬럼
;
SELECT 컬럼명 [, 컬럼명]
  FROM 테이블A 
           , 테이블B
 WHERE 테이블A.조인키컬럼(+) = 테이블B.조인키컬럼
;

  ANSI-SQL 구문에서는 FROM 절에 조인하고자 하는 두 테이블명 사이에 'RIGHT OUTER JOIN' 키워드를 입력합니다.
  ORACLE에서는 WHERE 절에서 왼쪽 테이블의 조인 키 컬럼명 뒤에 '(+)' 기호를 입력해줍니다.

  위 [예제 1] 상품 테이블과 고객주문상품 테이블을 Right outer join 하는 예제를 살펴보겠습니다.

-- ANSI-SQL
SQL> SELECT p.상품ID, p.상품명, o.상품ID, o.고객ID, o.주문일자, o.주문수량
    2>    FROM 상품 p
    3>   RIGHT OUTER JOIN 고객주문상품 o
    4>        ON p.상품ID = o.상품ID;

   조인하고자 하는 테이블명을 RIGHT OUTER JOIN 키워드를 기준으로 양쪽에 입력하고, 조인 조건은 ON 키워드 다음에 작성해줍니다.

-- ORACLE SQL
SQL> SELECT p.상품ID, p.상품명, o.상품ID, o.고객ID, o.주문일자, o.주문수량
    2>   FROM 상품 p
    3>            , 고객주문상품 o
    4>  WHERE p.상품ID(+) = o.상품ID;

  Oracle에서는 FROM 키워드 이후에 조인할 테이블명을 콤마(,)로 구분하여 나열해주고, WHERE절에 조인 조건을 작성하되, 왼쪽 테이블의 조인 키 컬럼명 뒤에 '(+)' 기호를 추가로 입력해줍니다.

  Right outer join의 결과는 아래와 같습니다.

  상품 테이블과 고객주문상품에서 조인 키 컬럼 값이 모두 존재하는 데이터와 오른쪽에 명시되었던 테이블의 고객주문상품 테이블에만 존재하는 데이터(상품ID가 5인 데이터)가 출력된 것을 확인하실 수 있습니다.
  오른쪽 고객주문상품 테이블에만 데이터가 존재하는 로우의 왼쪽 상품 테이블 컬럼 값은 NULL로 표시됩니다.

 

 

4. Full outer join

  Full outer join은집합 연산 결과와 같습니다. 
  조인 키 컬럼 값이 양쪽 테이블 데이터 집합에서 공통적으로 존재하는 데이터와 한쪽 테이블에만 존재하는
데이터도 모두 결과 데이터 집합으로 추출하게 됩니다.

  Full outer join 구문은 아래와 같습니다.

ANSI-SQL ORACLE SQL
SELECT 컬럼명 [, 컬럼명]
  FROM 테이블A  
  FULL OUTER JOIN 테이블B 
        ON 테이블A.조인키컬럼 = 테이블B.조인키컬럼
;
SELECT 컬럼명 [, 컬럼명]
  FROM 테이블A  
  FULL OUTER JOIN 테이블B 
       ON 테이블A.조인키컬럼 = 테이블B.조인키컬럼
;

  ANSI-SQL 구문에서는 FROM 절에 조인하고자 하는 두 테이블명 사이에 'FULL OUTER JOIN' 키워드를 입력합니다.
  ORACLE에서 '(+)' 기호를 이용한 Full outer join은 지원하고 있지 않습니다. Full outer join은 ANSI-SQL 구문 형식과 동일하게 사용하면 됩니다.

  위 [예제 1] 상품 테이블과 고객주문상품 테이블을 Right outer join 하는 예제를 살펴보겠습니다.

-- ANSI-SQL & ORACLE SQL
SQL> SELECT p.상품ID, p.상품명, o.상품ID, o.고객ID, o.주문일자, o.주문수량
    2>    FROM 상품 p
    3>     FULL OUTER JOIN 고객주문상품 o
    4>        ON p.상품ID = o.상품ID;

   조인하고자 하는 테이블명을 FULL OUTER JOIN 키워드를 기준으로 양쪽에 입력하고, 조인 조건은 ON 키워드 다음에 작성해줍니다.

  Full outer join의 결과는 아래와 같습니다.

  상품 테이블과 고객주문상품에서 조인 키 컬럼 값이 모두 존재하는 데이터와 상품 및 고객주문상품 테이블에만 존재하는 데이터(상품ID가 4,5인 데이터)가 출력된 것을 확인하실 수 있습니다.
  왼쪽 상품 테이블에만 데이터가 존재하는 로우의 오른쪽 고객주문상품 테이블 컬럼 값은 NULL로, 오른쪽 고객주문상품 테이블에만 데이터가 존재하는 로우의 왼쪽 상품 테이블 컬럼 값도 NULL로 출력됩니다.

 

  이상으로 조인의 종류에 대해 알아봤습니다.

  다음 포스트에서는 조인 방식(Methods)에 대해 설명드리도록 하겠습니다.
  조인 종류는 한쪽 테이블에만 존재하는 로우의 출력 여부를 기준으로 조인을 구분한 것이라면,
  조인 방식은 각 로우를 매핑을 하는 매커니즘에 따라 조인을 구분한다고 보시면 됩니다.
  더 자세한 내용은 아래 포스트를 참고해주세요.

 

테이블 조인 방식(Table join method)

테이블 조인 방식은 테이블의 각 로우를 매핑 시 어떤 메커니즘을 사용하느냐에 따라 조인을 구분하는 겁니다. 데이터 셋의 건수 등을 기반으로 옵티마이져가 적합한 조인 메커니즘을 선택하여 실행 계획을 생성하..

sparkdia.tistory.com

 

'Database' 카테고리의 다른 글

RDBMS 성능 최적화 전략  (0) 2020.04.09
SQL tuning 작업은 이제 불필요하다?  (0) 2020.03.16
Cassandra cqlsh 기본 사용법  (0) 2016.02.11
Cassandra 설치 2  (0) 2016.02.11
Cassandra 설치 1 - 사전 작업 (JDK, Python)  (0) 2016.02.11

+ Recent posts