하기 쿼리를 작성하였는데 속도가 안나네요.
어떻게 하면 좀 더 속도를 낼수 있을까요?
SELECT COL_1 --지차체명
,COL_2 --배출량
,COL_3 --처리량
,DECODE(AA2.COL_4, 0, 0, ROUND(((AA1.COL_2+AA1.COL_3)/AA2.COL_4) * 100,0)) COL4 --비율
FROM (
SELECT '1' DIV
,COL_1
, SUM(COL_2) COL_2
,SUM(COL_3) COL_3
FROM
(
SELECT
GRC_INFO.CMPTNC_NM COL_1--관할관청
,ROUND(SUM(DECODE( GIVE_QUN_NIT, '01', GIV_UNT, '02', GIV_UNT/1000, GIV_UNT/1000000)),0) COL_2
,0 COL_3
FROM
(SELECT *
FROM (
SELECT AB.*
FROM
MAN1000 AB
WHERE AB.GIVE_DATE BETWEEN TO_TIMESTAMP('20200101', 'YYYYMMDD') AND TO_TIMESTAMP('20201231', 'YYYYMMDD')
) AAB
) A1
JOIN BAS1000 BAS1000
ON BAS1000.ENTN = a1.EMI_CHRG
JOIN T_ST_CMPTNC_STDR_INFO GRC_INFO
ON (GRC_INFO.CERFIN_GRC_CD = NVL(BAS1000.CITY_AUTH, BAS1000.CMPT_AUTH))
AND GRC_INFO.CMPTNC_CD = '900' --'062'
WHERE 1 = 1
GROUP BY GRC_INFO.CMPTNC_GRC_GROUP_NM
UNION ALL
SELECT
GRC_INFO.CMPTNC_NM COL_1
,0 COL_2
,ROUND(SUM(DECODE( GIVE_QUN_NIT, '01', GIV_UNT, '02', GIV_UNT/1000, GIV_UNT/1000000)),0) COL_3
FROM
(SELECT *
FROM (
SELECT AB.*
FROM
MAN1000 AB
WHERE AB.GIVE_DATE BETWEEN TO_TIMESTAMP('20200101', 'YYYYMMDD') AND TO_TIMESTAMP('20201231', 'YYYYMMDD')
) AAB
) A0
JOIN man2000 a1
ON A0.MAN_NUMS = A1.MAN_NUMS
JOIN BAS1000 BAS1000
ON BAS1000.ENTN = a1.TRT_CHRG
JOIN T_ST_CMPTNC_STDR_INFO GRC_INFO
ON (GRC_INFO.CERFIN_ISSU_CD = NVL(BAS1000.CITY_AUTH, BAS1000.CMPT_AUTH))
AND GRC_INFO.CMPTNC_CD = '900' --'062'
WHERE 1 = 1
GROUP BY GRC_INFO.CMPTNC_NM
) AAA1
GROUP BY COL_1
) AA1
LEFT JOIN (
SELECT '1' DIV
,SUM(COL_2) + SUM(COL_3) COL_4
FROM
(
SELECT
GRC_INFO.CMPTNC_NM COL_1--관할관청
,ROUND(SUM(DECODE( GIVE_QUNT_UNIT, '01', GIVE_QUNT, '02', GIVE_QUNT/1000, GIVE_QUNT/1000000)),0) COL_2
,0 COL_3
FROM (SELECT *
FROM (
SELECT AB.*
FROM
MAN1000 AB
WHERE AB.GIVE_DATE BETWEEN TO_TIMESTAMP('20200101', 'YYYYMMDD') AND TO_TIMESTAMP('20201231', 'YYYYMMDD')
) AAB
) A1
JOIN BAS1000 BAS1000
ON BAS100.ENTN = a1.EMI_CHRG
JOIN T_ST_CMPTNC_STDR_INFO GRC_INFO
ON (GRC_INFO.CERFIN_ISSU_CD = NVL(BAS1000.CITY_AUTH, BAS1000.CMPT_AUTH))
AND GRC_INFO.CMPTNC_CD = '900' --'062'
WHERE
1 = 1
GROUP BY GRC_INFO.CMPTNC_NM
UNION ALL
SELECT
GRC_INFO.CMPTNC_NM COL_1
,0 COL_2
,ROUND(SUM(DECODE( RECV_QUNT_UNIT, '01',RECV_QUNT, '02', RECV_QUNT/1000, RECV_QUNT/1000000)),0) COL_3
FROM
(SELECT *
FROM man2000
WHERE RECV_DATE BETWEEN TO_TIMESTAMP('20200101', 'YYYYMMDD') AND TO_TIMESTAMP('20201231', 'YYYYMMDD')
) a1
JOIN BAS1000 BAS1000
ON BAS1000.ENTN = a1.TRTM_CHRG
JOIN T_ST_CMPTNC_STDR_INFO GRC_INFO
ON (GRC_INFO.CERFIN_ISSU_CD = NVL(BAS1000.CITY_AUTH, BAS100.CMPT_AUTH))
AND GRC_INFO.CMPTNC_CD = '900' --'062'
WHERE 1 = 1
GROUP BY GRC_INFO.CMPTNC_NM
) AAAA2
) AA2
ON AA1.DIV = AA2.DIV
1. 날짜 조건
- give_date, recv_date 의 data type 이 뭔가요?
- to_timestamp 를 사용하는게 맞나요?
- 해당 컬럼이 timestamp 형식이라면? 밀리초단위까지 저장되어 있지 않나요?
- 밀리초까지 저장되어 있다면? '20201231' 조건은 잘못된 조건입니다. 마지막 날짜 누락.
2. 쿼리가 일관성이 없는데?
- aa1 의 col3 에서는 man1000 의 give_date 조건주고 man2000 과 조인하고 give_qunt 을 이용하는데?
- aa2 의 col3 에서는 man2000 의 recv_date 조건주고 man1000 과 조인없이 recv_qunt 을 이용하네요?
- 서로 같은 조건으로 뽑아야 하는게 아닌지?
3. 불필요한 인라인뷰 사용
- aab, a0, a1 등의 인라인뷰 사용은 불필요합니다.
1. 날짜 조건
- give_date, recv_date 의 data type 이 뭔가요? => date 타입입니다.
- to_timestamp 를 사용하는게 맞나요? => date타입이다보니 to_timestamp 함수를 썼습니다.
- 해당 컬럼이 timestamp 형식이라면? 밀리초단위까지 저장되어 있지 않나요? => 밀리초단위까지 저장되어 있습니다.
- 밀리초까지 저장되어 있다면? '20201231' 조건은 잘못된 조건입니다. 마지막 날짜 누락. => 아...
2. 쿼리가 일관성이 없는데?
- aa1 의 col3 에서는 man1000 의 give_date 조건주고 man2000 과 조인하고 give_qunt 을 이용하는데?
- aa2 의 col3 에서는 man2000 의 recv_date 조건주고 man1000 과 조인없이 recv_qunt 을 이용하네요? => 데이터정보를 가져오는 테이블이 조금 다르다보니 그 테이블의 날짜정보로 조건을 주었습니다.
- 서로 같은 조건으로 뽑아야 하는게 아닌지? => 이 말씀 참고하겠습니다.
3. 불필요한 인라인뷰 사용
- aab, a0, a1 등의 인라인뷰 사용은 불필요합니다. => 참고하겠습니다.
1. Date 컬럼이라면? Timestamp 가 아닌 Date 조건을 줘야죠
- AND give_date >= TO_DATE('20200101', 'yyyymmdd')
- AND give_date < TO_DATE('20201231', 'yyyymmdd') + 1
2. 일관성이 없는 쿼리 부분
- 조건이 서로 다른 부분을 동일하게 조건을 맞춰 준다면?
- 쿼리를 개별 처리하여 조인할 필요가 없습니다.
- 분석함수를 통한 비율 계산이 가능해 집니다.
- RATIO_TO_REPORT http://gurubee.net/lecture/2675