where조건만 다른경우 동일 대용량 테이블을 한번만 사용가능한지 문의합니다. 0 19 545

by 김기화 [SQL Query] [2020.03.30 01:46:57]


아래 쿼리문에서 상품권 충전포인트 가져오는 쿼리문과 소멸예정일자 가져오는 쿼리문이 각각 두개로 

작성했는데, WHERE 조건문만 조금 차이나는 부분이 있습니다.

상품권 충전포인트 쿼리문에서는 원적립추가 이하부분과 소멸예정일자 가져오는 쿼리문에서는 

WHERE 조건문에서 소멸예정일자 조건문이 추가된 부분이 상품권 충전포인트 쿼리문과 다릅니다.

대용량 테이블이라 상품권충전 포인트 쿼리문과, 소멸예정일자 쿼리문을 한개의 쿼리문으로 작성이 

가능 할까요?

필드명 : RVG_PNT(적립포인트), UG_PNT(사용포인트)

SELECT 
    NVL(MAX(( SELECT SUM(GIFT_CARD_RM_PNT)
               FROM (SELECT CASE WHEN A.TR_DS_C = '20'
                                 THEN - A.RVG_PNT
                                 ELSE A.RVG_PNT
                            END
                          - NVL(SUM(B.UG_PNT), 0) GIFT_CARD_RM_PNT
                       FROM TB_MP_SA_AH_BASERVGBRK A
                          , TB_MP_SA_AH_BASEUGBRK B
                          , TB_MP_SA_AH_BASERVGBRK C
                      WHERE A.RVG_APV_LED_DTL_NO = B.RVG_APV_LED_DTL_NO (+)
                        AND A.USCAN_ATF_APV_LED_DTL_NO  = B.USCAN_ATF_APV_LED_DTL_NO (+)

AND A.RVG_APV_LED_DTL_NO = C.RVG_APV_LED_DTL_NO
                        AND A.INTG_MB_NO = '5000040267'
                        AND A.XHT_STS_YN = 'N'
                        AND C.USCAN_ATF_APV_LED_DTL_NO = LPAD(0, 18, '0')   -- 원적립추가
                        AND C.TR_RSN_C = '0503'
                      GROUP BY A.RVG_APV_LED_DTL_NO
                            , CASE WHEN A.TR_DS_C = '20' THEN - A.RVG_PNT ELSE A.RVG_PNT END
                     )
            )), 0) AS GIFT_CARD_RM_PNT   /* 상품권 충전 포인트 */
   , NVL(MAX(( SELECT SUM(XTT_PLA_PNT)
               FROM (SELECT CASE WHEN A.TR_DS_C = '20' THEN - A.RVG_PNT ELSE A.RVG_PNT END
                          - NVL(SUM(CASE WHEN B.TR_TP_C = '14' THEN - B.UG_PNT
                           ELSE B.UG_PNT END), 0) XTT_PLA_PNT
                       FROM TB_MP_SA_AH_BASERVGBRK A
                          , TB_MP_SA_AH_BASEUGBRK B
                      WHERE A.RVG_APV_LED_DTL_NO = B.RVG_APV_LED_DTL_NO (+)
                        AND A.USCAN_ATF_APV_LED_DTL_NO  = B.USCAN_ATF_APV_LED_DTL_NO (+)
                        AND A.INTG_MB_NO = '5000040267'
                        AND A.XHT_STS_YN = 'N'
                                                AND A.XTT_PLA_DT BETWEEN TO_CHAR(TO_DATE(TO_CHAR(SYSDATE, 'YYYYMM') || '01', 'YYYYMMDD'), 'YYYYMMDD')                        -- 소멸예정일자
                                                                     AND TO_CHAR(LAST_DAY(TO_DATE(TO_CHAR(SYSDATE, 'YYYYMM') || '01', 'YYYYMMDD')), 'YYYYMMDD')
                      GROUP BY CASE WHEN A.TR_DS_C = '20' THEN - A.RVG_PNT ELSE A.RVG_PNT END
                     )
            )), 0) AS XTT_PLA_PNT    /* 소멸예정 포인트 */            
   FROM TB_MP_AP_MH_PHTINF A
  WHERE A.INTG_MB_NO = '5000040267'
  ;

by 마농 [2020.03.30 08:39:51]

올려주신 쿼리가 이상하네요.


by 김기화 [2020.03.30 09:29:12]

어느 부분이 이상한가요?


by 마농 [2020.03.30 09:37:16]

첫번째 서브쿼리 부분이 이상해요. 문법이 안맞는데요. 조인도 이상하고.
 - TB_MP_SA)AH_BASERVGBRK 이부분 괄호도 이상하고
 - C.USCAN ATF_APV_LED_DTL_NO 이부분 공백도 이상하고


by 김기화 [2020.03.30 09:57:18]

아, 죄송합니다. 오타네요.

TB_MP_SA)AH_BASERVGBRK 괄호가 아니라 _ 입니다.
 - C.USCAN ATF_APV_LED_DTL_NO 도 공백이 아니라 _ 입니다.


by 마농 [2020.03.30 10:16:13]

오타 말고도 그냥 전반적으로 이상해요.
c 테이블에 대한 조인 조건도 없고?
메인 테이블은 아무 의미 없이 사용되었고?


by 김기화 [2020.03.30 10:42:14]

죄송합니다. 쿼리문 다시 수정했습니다.


by 마농 [2020.03.30 13:03:16]

그래도 여전히 이상하네요.
각 테이블의 키가 어떻게 되고, 테이블간의 관계가 어떻게 되나요?
각 조건절의 의미는 뭔가요?


by 김기화 [2020.03.30 15:52:22]

TB_MP_AP_MH_PNTINF:(포인트마스터테이블, pk는 회원번호:INTG_MB_NO)

TB_MP_SA_AH_BASERVGBRK(포인트적립테이블, pk는 적립원장번호:RVG_APV_LED_DTL_NO,적립원장상세번호:USCAN_ATF_APV_LED_DTL_NO)

TB_MP_SA_AH_BASERUGBRK:(포인트사용 테이블,pk는 사용원장번호:UG_APV_LED_DTL_NO,

적립원장번호:RVG_APV_LED_DTL_NO,

사용원장상세번호:USCAN_ATF_APV_LED_DTL_NO) 입니다

Where 절 쿼리문 설명 하자면 XHT_STS_YN는 포인트소멸여부 필드이며,

XTT_PLA_DT는 포인트소멸예정일자 이며

상품권 충전포인트의 합과 소멸예정인 포인트의 합을 구하는 쿼리문 입니다.

 

 


by 마농 [2020.03.30 16:44:12]

올려주신 정보와 쿼리의 테이블명과 컬럼명이 살짝씩 다른데 이것도 오타인가요?
- 포인트사용 테이블명이? tb_mp_sa_ah_baseugbrk / tb_mp_sa_ah_baserugbrk 뭐가 맞는지?
- 사용원장번호 컬럼명이? rvg_apv_led_dtl_no / ug_apv_led_dtl_no 뭐가 맞는지?
이렇게 오락가락 정보로 질문하시면 곤란합니다.


by 김기화 [2020.03.30 16:58:13]

죄송합니다. 급하게 스마트폰으로 입력하다보니 본의아니게 오타가 났습니다.

tb_mp_sa_ah_baseugbrk 가 맞습니다.

 


by 마농 [2020.03.30 16:59:51]

다음 조건의 의미가 뭔가요?
uscan_atf_apv_led_dtl_no = '000000000000000000'
tr_rsn_c = '0503'
tr_ds_c = '20'
tr_tp_c = '14'
위아래 쿼리의 조건이 다른 이유가 뭔가요?
같은 테이블 c 를 다시 조인하는 이유는?


by 김기화 [2020.03.30 17:02:41]

TB_MP_SA_AH_BASEUGBRK(포인트사용 테이블키는 UG_APV_LED_DTL_NO,RVG_APV_LED_DTL_NO,USCAN_ATF_APV_LED_DTL_NO로 세개의 컬럼으로 구성되었습니다.)


by 김기화 [2020.03.30 17:43:03]

tr_rsn_c = '0503' :거래사유가 상품권충전,tr_ds_c = '20' : 거래구분은 적립취소,

tr_tp_c = '14' : 거래유형은 상계증가 를 의미합니다.

같은테이블 c를 조인하는 이유는 포인트 적립시에 원적립건을 가져오기 위함입니다.


by 마농 [2020.03.30 18:29:09]

두 쿼리가 다른 이유는 뭔가요? 적립과 사용이 같은 기준으로 처리되어야 하는것 아닌가요?
 - 왜 tr_tp_c = '14' 조건이 아래쪽에만 있나요?
 - c는 위쪽에만 조인하고 아래쪽에는 조인 안하는 이유는?


by 김기화 [2020.03.31 00:11:58]

c는 위쪽에만 조인하는 이유는 원래의 포인트 적립건을 가져와야 하는 경우라서

AND C.USCAN_ATF_APV_LED_DTL_NO = LPAD(0, 18, '0')   이 조건문을 추가하게 되었고

TR_DS_C = '10' : 거래구분이 포인트 적립, TR_DS_C = '20' : 거래구분이 포인트 적립취소 의미임

tr_tp_c = '14' 조건이 아래쪽에 있는 것은 소멸예정 포인트를 계산하기 위해 상계증가분에 대한 조건이 추가된 건입니다.

아무튼 상품권 충전포인트의 합과 소멸예정 포인트 합을 구하는 where 조건이 조금 상이합니다.

(제가 직접적인 업무 담당자가 아니라 자세한 설명을 못드려서 죄송합니다)

결론적으로 

TB_MP_SA_AH_BASERVGBRK(포인트적립테이블) 과 TB_MP_SA_AH_BASERUGBRK(포인트사용 테이블)은 

대용량 데이터가 있어서 상품권 충전포인트의 합과 소멸예정 포인트 합 계산시 조건은 상이 하더라도

위 두테이블을 한번만 사용해서 상품권 충전포인트와 소멸예정 포인트 합의 쿼리문을 구현할수 있는지와

아니면 다른 방법으로 쿼리문을 작성할수 있는지 알려 주시면 고맙겠습니다. 

 


by 마농 [2020.03.31 08:24:28]

쿼리만 봤을 때 의문사항이 많은데 그에 대한 해소가 안되네요.
데이터를 볼 수 없으니 의문사항에 대한 검증도 못하고.
위에 언급은 안했지만. Group By 기준도 이해가 안가네요.
적립금으로 그룹바이 한다는게 좀 이상하네요.
지금의 불확실한 정보만으로는 쿼리만 보고 개선해 드릴 수 없습니다.

스칼라서브쿼리를 조인으로 풀면서
공통 조건은 Where 절에서 처리하고
개별 조건은 Case 문에서 처리하는 방식으로 집계를 하면 됩니다.


by 김기화 [2020.03.31 16:04:57]

스칼라서브쿼리를 조인으로 풀면서

공통조건은 where 절에서 처리하고

개별조건은case문에서 처리하는 방식에 대한

샘플쿼리좀 부탁해도 될까요?


by 마농 [2020.03.31 18:15:30]
-- 개선전 --
SELECT d.deptno
     , d.dname
     , (SELECT COUNT(*)
          FROM emp e
         WHERE e.deptno = d.deptno
           AND e.mgr IS NOT NULL
        ) cnt_tot
     , (SELECT COUNT(*)
          FROM emp e
         WHERE e.deptno = d.deptno
           AND e.mgr IS NOT NULL
           AND e.sal >= 2000
        ) cnt_sal_2000
     , (SELECT SUM(e.sal)
          FROM emp e
         WHERE e.deptno = d.deptno
           AND e.mgr IS NOT NULL
           AND e.job = 'CLERK'
        ) clerk_sal
  FROM dept d
 WHERE d.deptno < 50
 ORDER BY d.deptno
;
-- 개선후 --
SELECT d.deptno
     , d.dname
     , COUNT(e.deptno) cnt_tot
     , COUNT(CASE WHEN e.sal >= 2000 THEN 1 END) cnt_sal_2000
     , SUM(CASE WHEN e.job = 'CLERK' THEN e.sal END) clerk_sal
  FROM dept d
     , emp  e
 WHERE d.deptno = e.deptno(+)
   AND e.mgr(+) IS NOT NULL
   AND d.deptno < 50
 GROUP BY d.deptno, d.dname
 ORDER BY d.deptno
;

 


by 김기화 [2020.04.01 08:36:32]

감사합니다.

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