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 남용과 저렇게 테이블을 구성하면 안되는지 이유를 논리 정연하게 잘 설명할 수 있을까요?
업무를 모르는 상태서 말씀드리기 힘들지만 ( 대충봐서 그럴수도 ㅎㅎ)
일단 GROUP BY 랑 MAX랑은 전혀 다른값을 가져올수있어요.
DOC_NO 단위로 하위 데이터가 모두 같다면 MAX/MIN 값이 맞겠지만.
CU_CD 코드가 DOC_NO 단위에 서로다른 데이터가 온다면 값이 틀려집니다.
만일 동일한 값들이 들어오는 논리적 구조라하면 정규화가 안된것이라 보여집니다.
성능떄문에 정규화 하지 않는 경우도 있으니 정확하게 꼭 집어들이기 힘듭니다.
정규화는 일단 밑에 링크 참고하세요. 구루비 뒤져도 엄청 검색될겁니다.
http://wiki.gurubee.net/pages/viewpage.action?pageId=28115309