본문 바로가기

Algorithm

[ORACLE] 월/요일별 태어난 사람 통계 (DECODE, SUM, HAVING COUNT사용하기)

미션

  • 회원의 생일을 바탕으로 조건 추가 월/요일별 태어난 사람이 200이상인 경우만 표현
  • 각 컬럼별 case 사용안됨
SELECT MONTH 
    , GENDER
    , SUM(DECODE(DAY_OF_WEEK, '2', 1)) MON
    , SUM(DECODE(DAY_OF_WEEK, '3', 1)) MON
    , SUM(DECODE(DAY_OF_WEEK, '4', 1)) MON
    , SUM(DECODE(DAY_OF_WEEK, '5', 1)) MON
    , SUM(DECODE(DAY_OF_WEEK, '6', 1)) MON
    , SUM(DECODE(DAY_OF_WEEK, '1', 1)) MON
FROM (
	SELECT DECODE(SEX_CD, 'PLB401', '남자', 'PLB402','여자', NULL) GENDER
            ,  SUBSTR(CUBO.DEC(JUMIN),3, 2) AS MONTH
            ,  TO_CHAR(TO_DATE(CASE WHEN SUBSTR(CUBO.DEC(JUMIN), 7, 1) IN ('1', '2') THEN '19'
                            WHEN SUBSTR(CUBO.DEC(JUMIN), 7, 1) IN ('3', '4') THEN '20'
                            WHEN SUBSTR(CUBO.DEC(JUMIN), 7, 6) = '0000000' AND SUBSTR(CUBO.DEC(JUMIN), 1, 1) <> 0 THEN '19' END 
                || SUBSTR(CUBO.DEC(JUMIN), 0, 6), 'YYYYMMDD'), 'D') AS DAY_OF_WEEK
	FROM USER
	WHERE 1=1 
	AND LENGTH (CUBO.DEC(JUMIN)) = 13
	AND SUBSTR (CUBO.DEC(JUMIN), 7, 1) IN ( '1', '2', '3', '4')
	) 
WHERE 1=1 
AND GENDER IS NOT NULL
GROUP BY MONTH, GENDER
ORDER BY MONTH

 

어려움

 

1.  해당 요일에 태어난 사람이 200 명이 넘는 경우만 찍어줘야하는데 어째 죄다 찍힘

2. 17 초나 걸림 (심지어 맨 처음엔 27초였음)

 

해결

1. having count() 함수를 활용하여 집계 수에 따라 표시할 수 있도록 수정함

2. group by 로 한 번 더 감싸주니 5초가 되었다. 

 

SELECT MONTH 
    , GENDER
    , SUM(DECODE(DAY_OF_WEEK, '2', 1)) MON
    , SUM(DECODE(DAY_OF_WEEK, '3', 1)) MON
    , SUM(DECODE(DAY_OF_WEEK, '4', 1)) MON
    , SUM(DECODE(DAY_OF_WEEK, '5', 1)) MON
    , SUM(DECODE(DAY_OF_WEEK, '6', 1)) MON
    , SUM(DECODE(DAY_OF_WEEK, '1', 1)) MON
FROM (
        SELECT MONTH
            , GENDER
            , DAY_OF_WEEK
            , COUNT(*) CNT
        FROM (
                SELECT DECODE(SEX_CD, 'PLB401', '남자', 'PLB402','여자', NULL) GENDER
                    ,  SUBSTR(CUBO.DEC(JUMIN),3, 2) AS MONTH
                    ,  TO_CHAR(TO_DATE(CASE WHEN SUBSTR(CUBO.DEC(JUMIN), 7, 1) IN ('1', '2') THEN '19'
                                            WHEN SUBSTR(CUBO.DEC(JUMIN), 7, 1) IN ('3', '4') THEN '20'
                                            WHEN SUBSTR(CUBO.DEC(JUMIN), 7, 6) = '0000000' AND SUBSTR(CUBO.DEC(JUMIN), 1, 1) <> 0 THEN '19' END 
                                     	|| SUBSTR(CUBO.DEC(JUMIN), 0, 6), 'YYYYMMDD'), 'D') AS DAY_OF_WEEK
                FROM USER	
                WHERE 1=1 
                AND LENGTH (CUBO.DEC(JUMIN)) = 13
                AND SUBSTR (CUBO.DEC(JUMIN), 7, 1) IN ( '1', '2', '3', '4')
                )
        WHERE 1=1
        GROUP BY MONTH, GENDER, DAY_OF_WEEK
        HAVING COUNT(*) > 200
        )
GROUP BY MONTH, GENDER
ORDER BY MONTH

 

여러번 감싸면 오히려 느려질 줄 알았는데 이번 경우는 시간이 더 단축되는 효과를 볼 수 있었다. 불필요한 연산을 시키는 것보다는 여러번 감싸는게 좀 더 성능에 도움이 되는 모양이다.