Group by 남발에 대한 설명 0 2 1,052

by 웅아 [SQL Query] [2018.06.27 09:52:05]


SELECT FORM_KEY                                                        /* 양식키               */
     , DOC_NO                                                          /* 문서번호             */
     , TO_CHAR(TO_DATE(STD_DEAL_WR_DT),'YYYY-MM-DD') AS STD_DEAL_WR_DT /* 표준거래작성일자     */
     , CU_CD                                                           /* 거래처코드           */
     , CU_NM                                                           /* 거래처명             */
     , CU_REP_BSNM_NM                                                  /* 거래처대표사업자명   */
     , CU_ADDR                                                         /* 거래처주소           */
     , CU_BSNM_NO                                                      /* 거래처사업자번호     */
     , CU_MBTLNUM                                                      /* 거래처휴대폰번호     */
     , CU_EML                                                          /* 거래처이메일         */
     , DSTB_MNG_PSIC_EML                                               /* 유통관리담당자이메일 */
     , TRDE_PRIC_PAY_DT                                                /* 매매대금지급일자     */
     , TO_CHAR(TO_DATE(CT_STRDT),   'YYYY-MM-DD') AS CT_STRDT          /* 계약시작일자         */
     , TO_CHAR(TO_DATE(CT_ENDDT),   'YYYY-MM-DD') AS CT_ENDDT          /* 계약종료일자         */
     , TO_CHAR(TO_DATE(CT_EXTN_DT), 'YYYY-MM-DD') AS CT_EXTN_DT        /* 계약연장일자         */
     , CASE WHEN CT_STT = 'SA' THEN '저장'
            WHEN CT_STT = 'SU' THEN '등록'
            WHEN CT_STT = 'CF' THEN '확인'
            WHEN CT_STT = 'AP' THEN '승인'
            WHEN CT_STT = 'UP' THEN '업로드'
            WHEN CT_STT = 'FN' THEN '검토완료'
            WHEN CT_STT = 'EN' THEN '종료'
            ELSE '상태오류'
        END AS CT_STT                                                             /* 계약상태          */
     , NVL(TO_CHAR(STRE_DTTM     ,     'YYYYMMDD'),        '-') AS STRE_DTTM      /* 저장일시          */
     , TO_CHAR(    STRE_DTTM     ,     'YYYY-MM-DD HH24:MI:SS') AS STRE_DT        /* 저장일자          */
     , NVL(TO_CHAR(REG_DTTM      ,     'YYYYMMDD'),        '-') AS REG_DTTM       /* 등록일시          */
     , TO_CHAR(    REG_DTTM      ,     'YYYY-MM-DD HH24:MI:SS') AS REG_DT         /* 등록일자          */
     , NVL(TO_CHAR(CU_CF_DTTM    ,     'YYYYMMDD'),        '-') AS CU_CF_DTTM     /* 거래처확인일시    */
     , TO_CHAR(    CU_CF_DTTM    ,     'YYYY-MM-DD HH24:MI:SS') AS CU_CF_DT       /* 거래처확인일자    */
     , NVL(TO_CHAR(CU_AP_DTTM    ,     'YYYYMMDD'),        '-') AS CU_AP_DTTM     /* 거래처승인일시    */
     , TO_CHAR(    CU_AP_DTTM    ,     'YYYY-MM-DD HH24:MI:SS') AS CU_AP_DT       /* 거래처승인일자    */
     , NVL(TO_CHAR(CT_RVW_CM_DTTM,     'YYYYMMDD'),        '-') AS CT_RVW_CM_DTTM /* 계약검토완료일시  */
     , TO_CHAR(    CT_RVW_CM_DTTM,     'YYYY-MM-DD HH24:MI:SS') AS CT_RVW_CM_DT   /* 계약검토완료일자  */
     , NVL(TO_CHAR(CT_END_DTTM   ,     'YYYYMMDD'),        '-') AS CT_END_DTTM    /* 계약종료일시      */
     , TO_CHAR(    CT_END_DTTM   ,     'YYYY-MM-DD HH24:MI:SS') AS CT_END_DT      /* 계약종료일자      */
     , NVL(TO_CHAR(ULD_MDF_DTTM  ,     'YYYYMMDD'),        '-') AS ULD_MDF_DTTM   /* 업로드수정일시    */
     , TO_CHAR(    ULD_MDF_DTTM  ,     'YYYY-MM-DD HH24:MI:SS') AS ULD_MDF_DT     /* 업로드수정일자    */
     , CT_END_YN                                                                  /* 계약종료여부      */
     , MNGR_RVW_ID                                                                /* 관리자검토아이디  */
     , ULD_REG_DTTM                                                               /* 업로드등록일시    */
     , ULD_FILENM                                                                 /* 업로드파일명      */
     , DATA_REG_DTTM                                                              /* 데이터등록일시    */
     , DATA_MDF_DTTM                                                              /* 데이터수정일시    */
     , DATA_REG_ID                                                                /* 데이터등록아이디  */
     , DATA_MDF_ID                                                                /* 데이터수정아이디  */
     , COUNT(CT_PROD_CD) AS CT_PROD_CD_CNT                                        /* row수             */
  FROM TB_ODIF_MA01
 WHERE CT_PROD_CD = COALESCE(#{SEARCH_CT_PROD_CD}, CT_PROD_CD)
   AND (
        CU_CD LIKE '%' || #{SEARCH_CU_CD_NM}|| '%' OR
        CU_NM LIKE '%' || #{SEARCH_CU_CD_NM}|| '%'
       )
   AND DOC_NO   LIKE '%' ||  #{SEARCH_DOC_NO}|| '%'
   AND CT_STRDT LIKE '%' ||  #{SEARCH_CT_STRDT}|| '%'
   AND CT_STT     = COALESCE(#{SEARCH_CT_STT}, CT_STT)
 GROUP BY FORM_KEY
     , DOC_NO
     , STD_DEAL_WR_DT
     , CU_CD
     , CU_NM
     , CU_REP_BSNM_NM
     , CU_ADDR
     , CU_BSNM_NO
     , CU_MBTLNUM
     , CU_EML
     , DSTB_MNG_PSIC_EML
     , TRDE_PRIC_PAY_DT
     , CT_STRDT
     , CT_ENDDT
     , CT_EXTN_DT
     , CT_STT
     , STRE_DTTM
     , REG_DTTM
     , CU_CF_DTTM
     , CU_AP_DTTM
     , CT_RVW_CM_DTTM
     , CT_END_DTTM
     , CT_END_YN
     , MNGR_RVW_ID
     , ULD_MDF_DTTM
     , ULD_REG_DTTM
     , ULD_FILENM
     , DATA_REG_DTTM
     , DATA_MDF_DTTM
     , DATA_REG_ID
     , DATA_MDF_ID
 ORDER BY DOC_NO DESC

 

코드리뷰를 하던 중 이런 식으로 Group by를 남용해서 썼던데

 

Group by는 DOC_NO만 걸고 나머지 것들은 MAX나 카운트를 이용해 가져오면 될텐데

 

그리고 애초에 테이블 설계 자체를 이상하게 한것 같아서요

 

예를들면 주문 테이블이 있고 주문상세 테이블이 있는데 위 테이블은 주문상세만 있는 테이블 입니다.

 

그런 상태에서 리스트에는 Group by한 결과만을 뿌려주고요 데이터가 몇천건 이하일땐 위도 잘 돌아가겠지만

 

몇십만건 몇백만건이 있을땐 분명 문제가 되는 테이블인걸 인지 하고 있습니다.

 

어떤식으로 설명하면 Group 남용과 저렇게 테이블을 구성하면 안되는지 이유를 논리 정연하게 잘 설명할 수 있을까요?

by 우리집아찌 [2018.06.27 10:30:40]

업무를 모르는 상태서 말씀드리기 힘들지만 ( 대충봐서 그럴수도 ㅎㅎ)

일단 GROUP BY 랑 MAX랑은 전혀 다른값을 가져올수있어요.

DOC_NO 단위로 하위 데이터가 모두 같다면 MAX/MIN 값이 맞겠지만.

CU_CD 코드가 DOC_NO 단위에 서로다른 데이터가 온다면 값이 틀려집니다.

만일 동일한 값들이 들어오는 논리적 구조라하면 정규화가 안된것이라 보여집니다.

성능떄문에 정규화 하지 않는 경우도 있으니 정확하게 꼭 집어들이기 힘듭니다. 

정규화는 일단 밑에 링크 참고하세요. 구루비 뒤져도 엄청 검색될겁니다.

http://wiki.gurubee.net/pages/viewpage.action?pageId=28115309

  


by 마농 [2018.06.27 13:40:49]

조인 조건을 잘못 주어 중복 발생한걸 Group By 로 제거하려는 경향이 있는데
조인조건을 제대로 주어 중복이 발생하지 않도록 해야 하는데.
이걸 그냥 Group By 로 해결하려고 할 때 Group By 남용이라고 할 수 있습니다.
그런데 위 쿼리엔 조인이 없네요.
위 쿼리는 그냥 애초 설계 잘못인 듯 합니다.
주문테이블에 있어야 할 내용들이 주문상세에 중복되어 들어가 있는 경우겠네요.

댓글등록
SQL문을 포맷에 맞게(깔끔하게) 등록하려면 code() 버튼을 클릭하여 작성 하시면 됩니다.
로그인 사용자만 댓글을 작성 할 수 있습니다. 로그인, 회원가입