Вот начальный удар и может дать значительное улучшение. Многие из ваших запросов были коррелированными подзапросами, выполняемыми для каждой записи. Вместо этого я попытался построить агрегаты перед запросом по номеру учетной записи в разделе выбора из / присоединения. Сначала запрос, затем я объясню логи c после.
SELECT
CIAM.EXTERNAL_ID,
CMF_BALANCE.New_Charges / 100.0 "AMOUNT LAST BILL",
CCKs.Discount,
CCKs.Cycle,
AcntLast30.SumBalance "DEBT"
FROM
(SELECT
CMF.Account_No,
max( Bal.Bill_Ref_No ) MaxBillRef,
sum( case when Bal.PPDD_Date < TRUNC(SYSDATE )
then Bal.Balance_Due else 0 end ) SumBalance
from
BI_OWNER.CMF
JOIN BI_OWNER.CMF_BALANCE BAL
on CMF.Account_No = Bal.Account_No
where
CMF.PREV_CUTOFF_DATE > SYSDATE - 30
group by
CMF.Account_No ) AcntLast30
JOIN BI_OWNER.CUSTOMER_ID_ACCT_MAP CIAM
on AcntLast30.Account_No = CIAM.Account_No
AND CIAM.EXTERNAL_ID_TYPE = 1
JOIN BI_OWNER.CMF_BALANCE
on AcntLast30.Account_No = CMFBalance.Account_No
AND AcntLast30.MaxBillRef = CMFBalance.Bill_Ref_No
JOIN
(select
CC.Parent_Account_No,
CC.TOTAL_PERIODS "CYCLE",
'ACTIVE DISCOUNT' || ' ' || CCK.AVAIL_PERIODS || '/' || CC.TOTAL_PERIODS "DISCOUNT"
FROM
BI_OWNER.CUSTOMER_CONTRACT CC
JOIN BI_OWNER.CUSTOMER_CONTRACT_KEY CCK
ON CC.TRACKING_ID = CCK.TRACKING_ID
AND CC.TRACKING_ID_SERV = CCK.TRACKING_ID_SERV
AND ROWNUM = 1
JOIN ( select distinct Contract_Type
FROM CONTRACT_TYPES
WHERE PLAN_ID_DISCOUNT IS NOT NULL
AND DURATION_UNITS = -3) CT
on CC.Contract_Type = CT.Contract_Type
WHERE
CC.END_DT IS NULL ) CCKs
on AcntLast30.Account_No = CCKs.Parent_Account_No
В первоначальном предложении "FROM" у меня есть подзапрос, потому что вы, похоже, интересуетесь только учетными записями в течение последних 30 дней. Итак, пока я там, я присоединяюсь к вашей таблице CMF_Balance и получаю максимальное значение Bill_Ref_No для аккаунта И сумму баланса, когда PPDD_Date меньше TRUN C (sysdate), который является вашим столбцом результата "DEBT" , Итак, теперь у нас есть конечный список интересующих вас учетных записей с указанным счетом, максимальным счетом в файле и суммой задолженности.
(SELECT
CMF.Account_No,
max( Bal.Bill_Ref_No ) MaxBillRef,
sum( case when Bal.PPDD_Date < TRUNC(SYSDATE )
then Bal.Balance_Due else 0 end ) SumBalance
from
BI_OWNER.CMF
JOIN BI_OWNER.CMF_BALANCE BAL
on CMF.Account_No = Bal.Account_No
where
CMF.PREV_CUTOFF_DATE > SYSDATE - 30
group by
CMF.Account_No ) AcntLast30
Далее, просто присоединитесь к таблице CIAM, чтобы получить только счета для External_ID_Type = 1. Это тоже можно было бы объединить с приведенным выше запросом для результата псевдонима «AcntLast30».
JOIN BI_OWNER.CUSTOMER_ID_ACCT_MAP CIAM
on AcntLast30.Account_No = CIAM.Account_No
AND CIAM.EXTERNAL_ID_TYPE = 1
Теперь, поскольку запрос «AcntLast30» имеет учетную запись и ссылку на максимальный счет, к которой мы затем присоединяемся CMF_Balance для счета и ссылки # на счет, таким образом, дает нам CMF_BALANCE.New_Charges / 100.0 "AMOUNT LAST BILL"
JOIN BI_OWNER.CMF_BALANCE
on AcntLast30.Account_No = CMFBalance.Account_No
AND AcntLast30.MaxBillRef = CMFBalance.Bill_Ref_No
Наконец, псевдоним подзапроса приводит к "CCKs". Поскольку Discount и Cycle используют один и тот же запрос / подзапрос / существует, я просто запустил его один раз, который квалифицировал типы скидок, и извлек Account_No для условия JOIN. Теперь у нас есть значения Discount и Cycle для каждой учетной записи.
Если вы возвращаете так много строк, я полагаю, что производительность, полученная при предварительном отборе этих агрегатов перед запросом и присоединении к учетной записи, будет значительной быстрее, чем при каждом отдельном запросе в каждой строке.
Была ссылка на ROWNUM без какой-либо ссылки на таблицу / псевдоним, поэтому я не уверен, что это влияние в запросе.
Конечная нота Для таких вещей, как скидка, которая может быть неприменима, вам может потребоваться изменить ее на LEFT JOIN, для которой эти значения будут показаны как NULL. Но, не зная объема данных, декартовых произведений 1: много записей в данных таблицах, я думаю, это будет хорошо работать для вас. По большей части это выглядело так, как будто все привело к тому, что только одна запись была квалифицирована для каждой учетной записи, где важнее было объединение (например, ссылка на максимальный счет).