9-4-1. M:1:M 관계 조인


앞에서는 1:M:1 관계의 조인을 살펴봤다. 1:M:1은 인라인 뷰를 활용해도 되고 인라인 뷰를 활용하지 않아도 된다. 이제 소개할 M:1:M 관계는 가능하면 인라인 뷰를 활용해 처리해야 한다.

다양한 사이트에서 개발된 SQL들을 보면 M:1:M 관계를 인라인 뷰 없이 직접 조인 처리하는 실수를 많이 목격하게 된다. M:1:M 관계의 세 테이블은 일반적으로 직접 조인할 수 없다. 적절한 인라인 뷰와 GROUP BY 처리가 필요하다.

아래는 1(회원)을 중심으로 두 개의 M 테이블(주문, 이벤트응모)이 있는 M:1:M 관계다. 시스템의 업무가 많고 복잡할 수록 이와 같은 M:1:M 관계가 자주 만들어진다. 테이블 구조와 관계 자체는 정상적이다. 다만, 이러한 관계의 세 개 테이블을 조인할 때는 주의가 필요하다.

Untitled

M0253 회원에 대해 회원 정보와 주문 정보, 이벤트응모(EventEntry) 정보를 각각 조회해보자.

-- [SQL-9-4-1-a]
-- 회원 정보
SELECT  T1.MemberId ,T1.NickNm
FROM    startdb.Member T1
WHERE   T1.MemberId = 'M0253';

MemberId  NickNm  
--------  ------  
M0253     Cloud5 

-- [SQL-9-4-1-b]
-- 주문 정보(2019.10~2019.12), 주문금액이 8,000 이상만
SELECT  T2.MemberId ,T2.OrdNo ,T2.OrdDtm ,T2.OrdAmt
FROM    startdb.Ord T2
WHERE   T2.MemberId = 'M0253'
AND     T2.OrdDtm >= STR_TO_DATE('20191101','%Y%m%d')
AND     T2.OrdDtm <  STR_TO_DATE('20200101','%Y%m%d')
AND     T2.OrdAmt >= 8000
ORDER BY T2.OrdNo;

MemberId  OrdNo  OrdDtm               OrdAmt     
--------  -----  -------------------  ---------  
M0253     284    2019-11-11 11:00:00  8500.000   
M0253     730    2019-12-23 11:00:00  10000.000  
M0253     970    2019-12-25 11:00:00  12500.000  

-- [SQL-9-4-1-c]
-- 이벤트응모 정보(2019.10~2019.12)
SELECT  T3.MemberId ,T3.EventId, T3.EntryDtm
FROM    startdb.EventEntry T3
WHERE   T3.MemberId = 'M0253'
AND     T3.EntryDtm >= STR_TO_DATE('20191101','%Y%m%d')
AND     T3.EntryDtm <  STR_TO_DATE('20200101','%Y%m%d')
ORDER BY T3.EventId;

MemberId  EventId  EntryDtm             
--------  -------  -------------------  
M0253     EV0007   2019-11-07 08:07:13  
M0253     EV0008   2019-12-15 06:07:13  

위 세 테이블의 데이터를 조인해 아래와 같이 회원의 2019년 11월~12월 주문 건수(8,000원 이상의 주문)와 같은 기간의 이벤트 응모 횟수를 보여주려고 한다.

MemberId  NickNm  OrdCnt  EntryCnt  
--------  ------  ------  --------  
M0253     Cloud5  3       2         

Untitled