UNION ALL 이해하기


조인은 데이터 집합을 좌우로 연결한다. 반면에 UNION ALL은 데이터 집합을 상하로 연결한다.

아래는 UNION ALL을 사용해 매장 건수와 회원 건수, 상품 건수를 보여주는 SQL이다. 조인과 다르게 데이터 집합을 연결하는 조건을 고려하지 않아도 된다. UNION ALL로 연결 할 데이터 집합의 컬럼 수만 잘 맞추면 된다.

-- [SQL-7-12-1]
SELECT  'Shop' DV, COUNT(*) Cnt
FROM    startdb.Shop T1
UNION ALL
SELECT  'Member' DV, COUNT(*) Cnt
FROM    startdb.Member T2
UNION ALL
SELECT  'Item' DV, COUNT(*) Cnt
FROM    startdb.Item T3;

DV      Cnt   
------  ----  
Shop    300   
Member  9999  
Item    21    

UNION ALL을 사용할 때는 다음의 내용을 주의해야 한다.

아래는 주문년월별 주문금액과 주문건수를 보여주는 SQL이다.

-- [SQL-7-12-2]
SELECT  DATE_FORMAT(T1.OrdDtm,'%Y%m') OrdYm
        ,SUM(OrdAmt) OrdAmt
        ,COUNT(*) OrdCnt
FROM    startdb.Ord T1
WHERE   T1.OrdDtm >= STR_TO_DATE('20210101','%Y%m%d')
AND     T1.OrdDtm <  STR_TO_DATE('20210401','%Y%m%d')
GROUP BY DATE_FORMAT(T1.OrdDtm,'%Y%m');

OrdYm   OrdAmt       OrdCnt  
------  -----------  ------  
202101  2590000.000  501     
202102  3154500.000  610     
202103  3858000.000  746 

위 SQL의 결과를 보면 년월별로 주문금액과 주문건수가 각각의 컬럼으로 출력되고 있다. 위와 같은 결과를 아래와 같이 변형해보려고 한다. 주문금액과 주문건수를 컬럼이 아닌 로우로 분리하려고 하는 것이다.

OrdYm   VAL_Nm  VAL          
------  ------  -----------  
202101  AMT     2590000.000  
202102  AMT     3154500.000  
202103  AMT     3858000.000  
202101  CNT     501.000      
202102  CNT     610.000      
202103  CNT     746.000      

위와 같은 결과는 UNION ALL을 활용하면 쉽게 구할 수 있다. 년월별 주문금액 SQL과 년월별 주문건수 SQL을 각각 구해서 UNION ALL 처리하면 된다. 아래와 같다.

-- [SQL-7-12-3]
SELECT  DATE_FORMAT(T1.OrdDtm,'%Y%m') OrdYm
        ,'AMT' VAL_Nm
        ,SUM(OrdAmt) VAL
FROM    startdb.Ord T1
WHERE   T1.OrdDtm >= STR_TO_DATE('20210101','%Y%m%d')
AND     T1.OrdDtm <  STR_TO_DATE('20210401','%Y%m%d')
GROUP BY DATE_FORMAT(T1.OrdDtm,'%Y%m')
UNION ALL
SELECT  DATE_FORMAT(T1.OrdDtm,'%Y%m') OrdYm
        ,'CNT' VAL_Nm
        ,COUNT(*) OrdCnt
FROM    startdb.Ord T1
WHERE   T1.OrdDtm >= STR_TO_DATE('20210101','%Y%m%d')
AND     T1.OrdDtm <  STR_TO_DATE('20210401','%Y%m%d')
GROUP BY DATE_FORMAT(T1.OrdDtm,'%Y%m');