CASE는 생각보다 다양한 곳에 사용할 수 있다.

GROUP BY 항목에 CASE 사용


GROUP BY에 컬럼을 변형해 사용할 수 있는 것처럼 GROUP BY에 CASE도 사용할 수 있다. 아래는 CASE를 적용한 항목 자체를 GROUP BY 처리하는 예제다. CASE를 사용해 ShopDv를 처리하고 ShopDv에 따라 데이터를 그룹핑한다.

-- [SQL-6-2-1]
-- GROUP BY 적용 전 SQL
-- CASE를 사용해 S001 매장과 나머지 매장으로 구분해서 ShopDv를 출력
SELECT  T1.ShopId
        ,CASE WHEN T1.ShopId = 'S001' THEN 'S001매장' ELSE '나머지매장' END ShopDv
        ,T1.OrdDtm
        ,T1.OrdNo
        ,T1.OrdAmt
FROM    startdb.Ord T1
WHERE   T1.OrdDtm >= STR_TO_DATE('20230330','%Y%m%d')
AND     T1.OrdDtm <  STR_TO_DATE('20230331','%Y%m%d')
ORDER BY T1.ShopId;

ShopId  ShopDv     OrdDtm               OrdNo  OrdAmt     
------  --------   -------------------  -----  ---------  
S001    S001매장   2023-03-30 16:00:00  89036  4500.000   
S001    S001매장   2023-03-30 16:00:00  89094  5000.000   
... 생략 ...
S272    나머지매장  2023-03-30 12:30:00  88283  4000.000   
S274    나머지매장  2023-03-30 12:30:00  88284  4500.000   

-- [SQL-6-2-2]
-- CASE를 사용한 ShopDv 로직을 GROUP BY에 그대로 사용
SELECT  CASE WHEN T1.ShopId = 'S001' THEN 'S001매장' ELSE '나머지매장' END ShopDv
        ,SUM(T1.OrdAmt) OrdAtm
FROM    startdb.Ord T1
WHERE   T1.OrdDtm >= STR_TO_DATE('20230330','%Y%m%d')
AND     T1.OrdDtm <  STR_TO_DATE('20230331','%Y%m%d')
GROUP BY CASE WHEN T1.ShopId = 'S001' THEN 'S001매장' ELSE '나머지매장' END;

ShopDv      OrdAtm        
----------  ------------  
나머지매장  13209500.000  
S001매장    1399000.000   

아래는 주문시간대구분을 CASE로 처리한 후에, GROUP BY 처리한 예다. 어느 시간대 주문이 많은지 확인하는데 도움이 될 수 있다.

-- [SQL-6-2-3]
-- GROUP BY 적용전 SQL
-- DATE_FORMAT을 사용해 OrdDtm의 시간 부분을 추출하고 그에 따라 주문시간대구분을 처리
SELECT  T1.OrdNo ,T1.OrdDtm ,DATE_FORMAT(T1.OrdDtm,'%H') 주문시간
        ,CASE   WHEN DATE_FORMAT(T1.OrdDtm,'%H') < '10' THEN '10시이전주문'
                WHEN DATE_FORMAT(T1.OrdDtm,'%H') < '12' THEN '12시이전주문'
                WHEN DATE_FORMAT(T1.OrdDtm,'%H') < '17' THEN '17시이전주문'
                ELSE '17시이후주문'
        END 주문시간대구분
FROM    startdb.Ord T1
WHERE   T1.OrdDtm >= STR_TO_DATE('20201205','%Y%m%d')
AND     T1.OrdDtm <  STR_TO_DATE('20201206','%Y%m%d')
ORDER BY T1.OrdDtm ASC;

OrdNo  OrdDtm               주문시간  주문시간대구분         
-----  -------------------  --------  --------------  
7585   2020-12-05 08:00:00  08        10시이전주문    
7586   2020-12-05 08:00:00  08        10시이전주문    
... 생략 ...
7663   2020-12-05 13:00:00  13        17시이전주문    
7664   2020-12-05 13:00:00  13        17시이전주문    

-- [SQL-6-2-4]
-- GROUP BY 적용후 SQL, CASE를 GROUP BY 항목으로 사용
SELECT  CASE    WHEN DATE_FORMAT(T1.OrdDtm,'%H') < '10' THEN '10시이전주문'
                WHEN DATE_FORMAT(T1.OrdDtm,'%H') < '12' THEN '12시이전주문'
                WHEN DATE_FORMAT(T1.OrdDtm,'%H') < '17' THEN '17시이전주문'
                ELSE '17시이후주문'
        END 주문시간대구분
        ,COUNT(*) 주문시간대별주문건수
FROM    startdb.Ord T1
WHERE   T1.OrdDtm >= STR_TO_DATE('20201205','%Y%m%d')
AND     T1.OrdDtm <  STR_TO_DATE('20201206','%Y%m%d')
GROUP BY CASE   WHEN DATE_FORMAT(T1.OrdDtm,'%H') < '10' THEN '10시이전주문'
                WHEN DATE_FORMAT(T1.OrdDtm,'%H') < '12' THEN '12시이전주문'
                WHEN DATE_FORMAT(T1.OrdDtm,'%H') < '17' THEN '17시이전주문'
                ELSE '17시이후주문'
         END -- 주문시간대구분: GROUP BY에서는 컬럼의 별칭을 사용하지 않도록 주의
ORDER BY 주문시간대구분 ASC;

주문시간대구분  주문시간대별주문건수            
--------------  --------------------  
10시이전주문    5                     
12시이전주문    37                    
17시이전주문    38                    

집계함수 처리된 값에 CASE 사용


아래는 GROUP BY가 아닌 집계함수가 처리된 값에 CASE를 사용하는 예제다. GROUP BY의 기본 원칙은 GROUP BY 절에 컬럼만 SELECT 절에 그대로 사용할 수 있고, 나머지 컬럼은 집계함수 처리해야 한다. CASE는 집계함수 처리된 결과에 사용되고 있으므로 문제 없이 실행된다.

-- [SQL-6-2-5]
-- 집계함수가 처리된 값에 CASE를 사용
SELECT  T1.ShopId
        ,SUM(T1.OrdAmt) OrdAmt
        ,CASE   WHEN SUM(T1.OrdAmt) >= 300000 THEN '30만이상'
                WHEN SUM(T1.OrdAmt) >= 200000 THEN '20만이상'
                ELSE '20만미만' END AmtDv
FROM    startdb.Ord T1
WHERE   T1.OrdDtm >= STR_TO_DATE('20230201','%Y%m%d')
AND     T1.OrdDtm <  STR_TO_DATE('20230301','%Y%m%d')
GROUP BY T1.ShopId
ORDER BY OrdAmt DESC;

ShopId  OrdAmt      AmtDv     
------  ----------  --------  
S001    709500.000  30만이상  
S200    386500.000  30만이상  
S202    348500.000  30만이상  
S016    256000.000  20만이상  
... 생략 ...

ORDER BY에 CASE 사용


CASE는 ORDER BY 절에도 사용할 수 있다. 아래는 특정 회원의 경우 0으로 치환하고 나머지는 1로 치환해 특정 회원이 무조건 먼저 나오도록 처리한 SQL이다. 나머지 회원은 OrdAmt 순서에 따라 출력 된다.