안녕하세요 DB초보입니다. 인라인 뷰를 사용해서 8개의 컬럼으로 된 하나의 행만 추출하려고 합니다. 그런데, 코드의 대부분이 중복됩니다. PL/SQL을 사용하면 될 것 같은데 PL/SQL을 잘 몰라서 어떻게 접근할지도 모르겠습니다. 'CARD_NUM' 컬럼과 'CARD_TRANSACTION_TIME' 컬럼에 인덱스를 생성해서 쿼리 속도가 많이 향상됐습니다. 그럼에도, 천만건의 데이터를 다루다보니 약간의 지연이 있습니다. 어떻게 하면 코드를 단순화하고 쿼리속도를 향상시킬 수 있을까요? WITH WHOLE AS (SELECT CARD_TRANSACTION_TIME, CARD_TRANSACTION_AMOUNT, CARD_TRANSACTION_CONTENT, INDUSTRY_CODE FROM CARD_TRANSACTION_TEST01 WHERE CARD_NUM IN(SELECT CARD_NUM FROM CARD_CONTRACT_TEST01 WHERE RESI_NUM = '9203101937988') AND TO_CHAR(CARD_TRANSACTION_TIME, 'YYYY') = '2020' AND TO_CHAR(CARD_TRANSACTION_TIME, 'MM') = '01' UNION ALL SELECT CARD_TRANSACTION_TIME, CARD_TRANSACTION_AMOUNT, CARD_TRANSACTION_CONTENT, INDUSTRY_CODE FROM OPEN_CARD_TRANSACTION_TEST01 WHERE RESI_NUM = '9203101937988' AND TO_CHAR(CARD_TRANSACTION_TIME, 'YYYY') = '2020' AND TO_CHAR(CARD_TRANSACTION_TIME, 'MM') = '01' AND MEANS IN('cardOne', 'cardTwo') ) SELECT SUBQUERY1.RESULT AS TYPE1, SUBQUERY2.RESULT AS "TYPE2", SUBQUERY3.RESULT AS "TYPE3", SUBQUERY4.RESULT AS "TYPE4", SUBQUERY5.RESULT AS "TYPE5", SUBQUERY6.RESULT AS "TYPE6", SUBQUERY7.RESULT AS "TYPE7", SUBQUERY8.RESULT AS "TYPE8" FROM (SELECT * FROM (SELECT SUM(RESULT) AS RESULT FROM( SELECT SUM(CARD_TRANSACTION_AMOUNT) AS RESULT FROM WHOLE GROUP BY INDUSTRY_CODE HAVING INDUSTRY_CODE IN('I1', 'I2') UNION ALL -- SELECT NULL AS NUM SELECT 0 AS RESULT FROM DUAL)) WHERE RESULT IS NOT NULL OR ROWNUM = 1) SUBQUERY1, (SELECT * FROM (SELECT SUM(RESULT) AS RESULT FROM( SELECT SUM(CARD_TRANSACTION_AMOUNT) AS RESULT FROM WHOLE GROUP BY INDUSTRY_CODE HAVING INDUSTRY_CODE IN('I4', 'I5', 'I6') UNION ALL -- SELECT NULL AS NUM SELECT 0 AS RESULT FROM DUAL)) WHERE RESULT IS NOT NULL OR ROWNUM = 1) SUBQUERY2, (SELECT * FROM (SELECT SUM(RESULT) AS RESULT FROM( SELECT SUM(CARD_TRANSACTION_AMOUNT) AS RESULT FROM WHOLE GROUP BY INDUSTRY_CODE HAVING INDUSTRY_CODE IN('I7', 'I8') UNION ALL -- SELECT NULL AS NUM SELECT 0 AS RESULT FROM DUAL)) WHERE RESULT IS NOT NULL OR ROWNUM = 1) SUBQUERY3, (SELECT * FROM (SELECT SUM(CARD_TRANSACTION_AMOUNT) AS RESULT FROM WHOLE GROUP BY INDUSTRY_CODE HAVING INDUSTRY_CODE IN('I9') UNION ALL -- SELECT NULL AS NUM SELECT 0 AS RESULT FROM DUAL) WHERE RESULT IS NOT NULL OR ROWNUM = 1) SUBQUERY4, (SELECT * FROM (SELECT SUM(CARD_TRANSACTION_AMOUNT) AS RESULT FROM WHOLE GROUP BY INDUSTRY_CODE HAVING INDUSTRY_CODE IN('I10') UNION ALL -- SELECT NULL AS NUM SELECT 0 AS RESULT FROM DUAL) WHERE RESULT IS NOT NULL OR ROWNUM = 1) SUBQUERY5, (SELECT * FROM (SELECT SUM(CARD_TRANSACTION_AMOUNT) AS RESULT FROM WHOLE GROUP BY INDUSTRY_CODE HAVING INDUSTRY_CODE IN('I11') UNION ALL -- SELECT NULL AS NUM SELECT 0 AS RESULT FROM DUAL) WHERE RESULT IS NOT NULL OR ROWNUM = 1) SUBQUERY6, (SELECT * FROM (SELECT SUM(CARD_TRANSACTION_AMOUNT) AS RESULT FROM WHOLE GROUP BY INDUSTRY_CODE HAVING INDUSTRY_CODE IN('I12') UNION ALL -- SELECT NULL AS NUM SELECT 0 AS RESULT FROM DUAL) WHERE RESULT IS NOT NULL OR ROWNUM = 1) SUBQUERY7, (SELECT * FROM (SELECT SUM(CARD_TRANSACTION_AMOUNT) AS RESULT FROM WHOLE GROUP BY INDUSTRY_CODE HAVING INDUSTRY_CODE IN('I13') UNION ALL -- SELECT NULL AS NUM SELECT 0 AS RESULT FROM DUAL) WHERE RESULT IS NOT NULL OR ROWNUM = 1) SUBQUERY8 WHERE ROWNUM <=1;
WITH whole AS ( -- 1. 컬럼을 가공하여 조건주지 말고 -> 조건을 가공 SELECT industry_code cd , card_transaction_amount amt FROM card_transaction_test01 WHERE card_num IN (SELECT card_num FROM card_contract_test01 WHERE resi_num = '9203101937988') AND card_transaction_time >= TO_DATE('2020'||'01', 'yyyymm') AND card_transaction_time < ADD_MONTHS(TO_DATE('2020'||'01', 'yyyymm'), 1) UNION ALL SELECT industry_code cd , card_transaction_amount amt FROM open_card_transaction_test01 WHERE resi_num = '9203101937988' AND means IN ('cardOne', 'cardTwo') AND card_transaction_time >= TO_DATE('2020'||'01', 'yyyymm') AND card_transaction_time < ADD_MONTHS(TO_DATE('2020'||'01', 'yyyymm'), 1) ) -- 2. SUM(CASE 를 이용한 피벗 구현으로 테이블 읽기 횟수 줄이기(8회 -> 1회) -- SELECT NVL(SUM(CASE WHEN cd IN ('I1', 'I2' ) THEN amt END), 0) type1 , NVL(SUM(CASE WHEN cd IN ('I4', 'I5', 'I6') THEN amt END), 0) type2 , NVL(SUM(CASE WHEN cd IN ('I7', 'I8' ) THEN amt END), 0) type3 , NVL(SUM(CASE WHEN cd IN ('I9' ) THEN amt END), 0) type4 , NVL(SUM(CASE WHEN cd IN ('I10' ) THEN amt END), 0) type5 , NVL(SUM(CASE WHEN cd IN ('I11' ) THEN amt END), 0) type6 , NVL(SUM(CASE WHEN cd IN ('I12' ) THEN amt END), 0) type7 , NVL(SUM(CASE WHEN cd IN ('I13' ) THEN amt END), 0) type8 FROM whole ;
-- 3. 2단계 집계로 CASE 함수 사용 횟수 줄이기( 8천만회(천만건*8번) -> 96회(12종*8번) ) -- SELECT NVL(SUM(CASE WHEN cd IN ('I1', 'I2' ) THEN amt END), 0) type1 , NVL(SUM(CASE WHEN cd IN ('I4', 'I5', 'I6') THEN amt END), 0) type2 , NVL(SUM(CASE WHEN cd IN ('I7', 'I8' ) THEN amt END), 0) type3 , NVL(SUM(CASE WHEN cd IN ('I9' ) THEN amt END), 0) type4 , NVL(SUM(CASE WHEN cd IN ('I10' ) THEN amt END), 0) type5 , NVL(SUM(CASE WHEN cd IN ('I11' ) THEN amt END), 0) type6 , NVL(SUM(CASE WHEN cd IN ('I12' ) THEN amt END), 0) type7 , NVL(SUM(CASE WHEN cd IN ('I13' ) THEN amt END), 0) type8 FROM (SELECT cd , SUM(amt) amt FROM whole GROUP BY cd ) ;