관계와 조인의 이해

HELLO_DINO·2022년 9월 15일
0

SQL전문가가이드

목록 보기
7/28

조인

조인 : 관계를 맺는다는 건 식별자를 상속하고, 상속된 속성을 매핑키로 활용해 데이터를 결합하는 걸 SQL에서 조인(join)이라고 한다.

여기서는 고객 엔터티의 식별자인 고객번호를 주문 엔터티에 상속시킨 것이다.

주문번호가 1100001인 주문의 고객명은?

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

이게 바로 관계를 활용한 조인이다.
2번과 3번이 조인이고, 고객번호가 조인키이다.
이를 SQL로 작성하면 아래와 같다.

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

계층형 데이터 모델

위의 모델은 자기 자신에게도 관계가 발생한다.
EMP 모델은 계층형 데이터 모델이다.


위의 표에서 MGR은 각 사원 관리자의 사원번호이다.

  1. EMP에서 ENAME이 'SMITH'인 데이터를 찾는다.
  2. 데이터의 행에서 MGR이 7902라는 것을 확인.
  3. EMP에서 EMPNO가 7902인 데이터를 찾는다.
  4. 행에서 ENAME이 'FORD"라는 것을 확인

이를 이용해 SQL로 나타내면 다음과 같다.

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

MGR 속성에는 EMPNO가 들어간다. 이를 매핑키로 활용해 조인할 수 있다.

EMP 데이터를 직관적으로 표현하면 아래 그림과 같다.

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

상호배타적 관계


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

위의 표의 주문 데이터를 보면, 개인/법인번호에는 개인고객 또는 법인고객의 식별자가 상속된 값이다.
고객구분코드의 값을 통해 개인고객의 식별자가 상속되었는지, 법인고객의 식별자가 상속되었는지를 나타낸다.
(고객구분코드 01: 개인고객, 02: 법인고객)

이를 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이 최선이다.

개인번호와 법인번호에 중복이 있으면 안되고 법인번호는 10자리이므로 개인번호가 십억 명을 초과하지 않는다면 문제가 되지 않지만, 그 이상이면 2건의 데이터가 출력될 수 있다.
이에 해당하는 경우라면 반드시 고객구분코드 값을 변수로 받아야 한다. 또한 개인번호와 법인번호가 중복되지 않는다는 전제가 있다면 다음과 같은 SQL도 가능하다.

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

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

두 방식의 SQL 차이점은, UNION ALL을 사용한 건 조인된 결과가 없다면 공집합(NO ROWS)을 출력한다. 아우터 조인을 활용한 건 결과가 없다면 NULL값을 가진 한 건의 ROWS(NULL ROWS)를 출력한다.

모델상으로는 반드시 둘 중 하나의 값을 가져야 하지만, 데이터 품질문제로 이와 같은 결과가 출력될 수도 있으니 이는 SQL 작성 시 고려해야 할 사안이다.

0개의 댓글