SQL-관계와 조인의 이해

박현·2022년 9월 4일
0

SQL

목록 보기
7/34
  • 조인(Join)
    :관계를 맺는다는 건 식별자를 상속하고, 상속된 속성을 매핑키로 활용하여 데이터를 결합해 볼 수 있다는 의미다.

조인


위의 모델은 고객과 주문엔터티가 관계를 맺고 있는 모습이다.
관계를 맺음으로 생기는 현상은 고객 엔터티의 식별자인 고객번호를 주문엔터티에 상속시킨 것이다. 즉 관계를 맺는다는 것은 식별자를 상속시키고 해당 식별자를 매핑키로 활용해 데이터를 결합하여 보겠다는 것이다.

--고객데이터--

고객번호고객명
100정우진
101한형식
102황영은

-- 주문데이터--

주문번호고객번호주문상태코드
1100001100주문완료
1100002101주문완료
1100003101취소요청
1100004102환불요청
1100005100교환완료

위 표의 주문데이터의 고객데이터에서 고객번호를 상속시킨 것을 볼 수 있다.
주문번호가 1100001인 주문의 고객명은 정우진이라는 것을 알수있다. 우리는 어떻게 고객명을 알수 있었을까? 이를 풀어보면 다음과 같다.

  • 주문데이터에서 주문번호가 1100001인 데이터를 찾는다
  • 주문번호가 1100001 데이터의 행에서 고객번호가 100임을 확인한다.
  • 고객데이터에서 고객번호가 100인 데이터를 찾는다.
  • 고객번호가 100인 데이터의 행에서 고객명인 정우진이라는 것을 확인한다.

위와 같은 순서로 고객명을 찾았다. 이것이 바로 관계를 활용한 조인이다.
관계에 의해 상속된 고객번호라는 속성을 가지고 주문데이터에서 매핑키로써 고객명을 찾아냈다. 두번째와 세번째가 조인이고 고객번호가 조인키이다. 이것을 SQL로 작성해본다면 다음과 같다.

SELECT B.고객명
FROM 주문 A, 고객 B
WHERE A.주문번호 = '1100001'
AND A.고객번호 = B.고객번호

계층형 데이터 모델

일반적인 관계는 위의 그림처럼 두 엔터티간에 발생한다. 하지만 자기 자신에게 관계가 발생하는 경우도 있다.

위의 모델은 Sample Schema로 제공되는 계층형 데이터 모델인 EMP(사원)모델이다.

  • 계층형 데이터 모델이란 무엇일까?
    : 말 그대로 계층구조를 가진 데이터를 지칭하는 것이다.

위 표에서 주목해야 할 속성은 MGR이다. MGR속성은 각 사원 관리자의 사원번호를 의미한다. 즉 SMITH의 관리자는 사원번호가 7902인 FORD가 된다. 그럼 FORD의 관리자는 누구일까 사원번호가 7566인 JONES이다. 관리자를 찾아가는 과정이 조인이라는 행동이다. 이를 SQL로 표현하면 다음과 같다.

SELECT B.EMANE
	FROM EMP A, EMP B
 WHERE A.ENAME='SMITH'
 	AND A.MGR=B.EMPNO

이전과 다른점은 자기자신을 조인했다는 것이다. 이를 셀프조인이라고한다.
이처럼 조인이 가능한 이유는 위의 사진을 보면 자기 자신에서 관계를 맺은 것을 볼 수 있다. 관계를 맺으면 식별자를 상속한다고 했다. 본모델에서는 상속된 식별자가 바로 MGR속성이다. 속성명만 다를 뿐 MGR속성에는 EMPNO가 들어간다. 이를 매핑키로 활용하여 조인할 수 있는 것이다.

즉 계층형 데이터 모델은 데이터 간의 계층이 존재할 때 발생하는 모델이라 할 수 있다. EMP데이터를 더 직관적으로 표현하면 다음과 같다.

다른예로 쇼핑몰에는 카테고리 정보가 대표적이다.

계층형 데이터 모델은 특수한 경우에만 발생하는 희귀한 모델은 아니다. 즉 업무에 따라 충분히 만날 수 있는 모델이기에 개념을 명확하게 알고 있어야 한다. 그래야 계층형 쿼리(Connect By절)을 만났을때 당황하지 않고 학습할 수 있다.


상호배타적 관계

상호배타적(Exclusive-OR)관계는 업무에 따라 얼마든지 만날 수 있으므로 개념 정도는 숙지하고 있어야 한다.

위의 모델은 개인, 법인고객이 존재하는 모델에서 주문과의 상호배타적 관계를 표현하고 있다. IE표기법에서는 상호배타적 관계표기를 지원하지 않아 괄호와 유사한 선을 직접그려준다. 본 모델에서는 관계의 배타적관계로서 주문엔터티에는 개인 또는 법인번호 둘중 하나만 상속될 수 있음을 의미한다. 즉 주문은 개인고객이거나 법인고객 둘중 하나의 고객만이 가능하다. 이를 데이터로 보면 더 명확하게 이해할 수 있다.

--주문데이터--

주문번호고객구분코드개인/법인번호
1100001011234
1100002021122334455
1100003011356
1100004012356
11000050222334455666

위 표의 주문데이터를 보면 개인/법인번호는 개인고객 또는 법인고객의 식별자가 상속된 값이다. 이때 고객구분코드의 값을 통해 개인고객의 식별자가 상속되었는지, 법인고객의 식별자가 상속되었는지를 나타낸다.
표에서 주문번호가 1100001인 주문의 주문자명을 보여주고 싶을때는 SQL을 다음과 같이 작성해야 한다.

SELECT B.개인고객명
	FROM 주문 A, 개인고객 B
WHERE A.주문번호=1100001
	AND A.고객구분코드='01'
    AND A.개인/법인번호=B.개인번호
UNION ALL
SELECT B.법인명
	FROM 주문 A, 법인고객 B
WHERE A.주문번호=1100001
	AND A.고객구분코드='02'
    AND A.개인/법인번호=B.법인번호

고객구분코드를 알 수 있다면 명확하게 개인고객 또는 법인고객 테이블을 선택하여 하나의 테이블만 조인하여 SQL을 작성할 수 있다. 그렇지 않은 경우라면 위와 같은 SQL이 최선이다. 이때 주의할점은 개인번호와 법인번호에 중복이 발생되어서는 안된다. 또한 개인번호와 법인번호가 중복되지 않는다는 전제가 있다면 다음과 같은 SQL도 가능하다.

SELECT COALESCE(B.개인고객명, C.법인명) 고객명
	FROM 주문 A LEFT JOIN 개인고객B
    ON (A.개인/법인번호=B.개인번호) LEFT OUTER JOIN 법인고객 C
    ON (A.개인.법인번호=C.법인번호)
 WHERE A.주문번호=1100001;

개인번호와 법인번호는 중복되지 않기에 아우터 조인으로 연결하였다. 둘 중 하나는 조인에 성공하기 때문에 위와 같이 SQL을 작성해도 무방하다. 단 SELECT절에서는 조인되는 테이블의 고객명을 가져와야 하기에 COALESCE함수를 사용하였다.

두 방식의 SQL차이점을 보면 UNION ALL을 사용한 첫번째 SQL은 만일 조인되는 결과가 없다면 공집합(NO ROWS)을 출력할것이다.
아우터 조인을 활용한 두번째 SQL은 조인되는 결과가 없다면 NULL값을 가진 한건의 ROWS를 출력하게 된다.


참고자료: SQL전문가가이드

0개의 댓글