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


두 테이블의 관계 차수를 파악하고, 두 테이블을 조인하는 것은 크게 어렵지 않다. 그리고 두 테이블은 1:M 관계로 이루어진 경우가 대부분이다. 결국, 두 테이블 간에 조인은 1:M 관계일 가능성이 높다. 이제는 난이도를 조금 높여서 세 테이블의 관계 차수를 살펴보고 그에 맞게 조인을 작성해보자.

아래는 매장, 주문, 회원 테이블이다. 매장과 주문은 1:M, 주문과 회원이 M:1이다. 그러므로 세 테이블은 주문을 중심으로 1:M:1 관계가 된다.

Untitled

Untitled

1:M:1과 같은 관계에서는 테이블 간에 조인 컬럼만 잘 고려해서 SQL을 작성하면 된다. 아래는 2018년 3월 27일에 오픈한 매장에 대해, 플래티넘 회원의 2020년 1월 주문을 조회하는 SQL이다.

-- [SQL-9-3-1-a] 1:M:1 조인
SELECT  T2.OrdNo ,T2.OrdDtm ,T2.OrdAmt
        ,T1.ShopId ,T1.ShopNm
        ,T3.MemberId ,T3.NickNm
FROM    startdb.Shop T1
        INNER JOIN startdb.Ord T2
            ON (T2.ShopId = T1.ShopId)
        INNER JOIN startdb.Member T3
            ON (T3.MemberId = T2.MemberId)
WHERE   T1.ShopStartYmd = '20180327'
AND     T2.OrdDtm >= STR_TO_DATE('20200101','%Y%m%d')
AND     T2.OrdDtm <  STR_TO_DATE('20200201','%Y%m%d')
AND     T3.MemberGd = 'PLAT';

OrdNo  OrdDtm               OrdAmt    ShopId  ShopNm         MemberId  NickNm     
-----  -------------------  --------  ------  -------------  --------  ---------  
1232   2020-01-02 13:00:00  8000.000  S028    San Diego-2nd  M0298     Thunder5   
1244   2020-01-05 10:00:00  8500.000  S014    Columbus-1st   M0291     Star5      
1285   2020-01-11 10:00:00  7500.000  S014    Columbus-1st   M0291     Star5      
1298   2020-01-11 11:00:00  4000.000  S014    Columbus-1st   M1283     Quantum25  
1315   2020-01-11 12:00:00  7500.000  S031    Austin-2nd     M1297     Swift25    
1352   2020-01-23 10:00:00  8500.000  S014    Columbus-1st   M0291     Star5      
1367   2020-01-23 11:00:00  4000.000  S014    Columbus-1st   M1283     Quantum25  
1387   2020-01-23 12:00:00  4000.000  S031    Austin-2nd     M1297     Swift25    
1414   2020-01-29 10:00:00  4000.000  S014    Columbus-1st   M0291     Star5      
1429   2020-01-29 11:00:00  4000.000  S014    Columbus-1st   M1283     Quantum25  
1449   2020-01-29 12:00:00  4000.000  S031    Austin-2nd     M1297     Swift25    
1486   2020-01-30 13:00:00  2500.000  S028    San Diego-2nd  M0298     Thunder5   

위 SQL은 아래 그림과 같이, Shop은 Ord만큼 데이터가 늘어나고, Member는 Shop과 Ord의 조인 결과만큼 데이터가 늘어난게 된다. 1:M:1 조인에서 1쪽은 M만큼 데이터가 늘어날 수 있다.

image.png

위 SQL을 조금더 발전시켜, MemberId별로 주문금액 합계를 구해보자. 다음과 같이 SQL을 변경하면 된다.

-- [SQL-9-3-1-b] 1:M:1 조인후 GROUP BY
SELECT  T3.MemberId ,MAX(T3.NickNm) NickNm
        ,SUM(T2.OrdAmt) SumOrdAmt
FROM    startdb.Shop T1
        INNER JOIN startdb.Ord T2
            ON (T2.ShopId = T1.ShopId)
        INNER JOIN startdb.Member T3
            ON (T3.MemberId = T2.MemberId)
WHERE   T1.ShopStartYmd = '20180327'
AND     T2.OrdDtm >= STR_TO_DATE('20200101','%Y%m%d')
AND     T2.OrdDtm <  STR_TO_DATE('20200201','%Y%m%d')
AND     T3.MemberGd = 'PLAT'
GROUP BY T3.MemberId
ORDER BY T3.MemberId;

MemberId  NickNm     SumOrdAmt  
--------  ---------  ----------  
M0291     Star5      28500.000   
M0298     Thunder5   10500.000   
M1283     Quantum25  12000.000   
M1297     Swift25    15500.000    

1:M:1 관계를 모두 조인 후 GROUP BY 처리했다. 데이터 집합이 처리되는 과정을 개념적으로 그려보면 다음과 같다. 1인 데이터 집합은 M쪽 만큼 데이터가 늘어난 후, GROUP BY 컬럼의 값 종류만큼 줄어들게 된다.