Oracle SQL UNION ALL со значением NULL вызывает проблемы с производительностью при попытке внешнего объединения данных

Я пытаюсь создать запрос, который возвращает клиентов из Oracle и их заметки. К сожалению, таблицы заметок, из которых я выбираю данные, не имеют соединений 1-1 с клиентами, поэтому я присоединяюсь к данным с помощью идентификатора стороны и ищу определенную строку в заметках, которые содержат номер контракта клиента.

Я хочу вернуть информацию о клиенте, контракте и их примечаниях, если примечания существуют и если примечания не существуют.

Я знаю, что приведенный ниже код является длинным, но меня особенно интересует, как обрабатывать самый последний бит кода (поэтому код, в котором я объединяюсь с информацией примечаний в конце). Проблема, с которой я столкнулся в текущей версии запроса, заключается в том, что если я присоединяюсь к подзапросам FORCE_NOTE_GUAR и FORCE_NOTE_CUST, добавляя UNION ALL с нулями, производительность очень и очень плохая.

Если я удалю этот UNION ALL, производительность будет хорошей, однако я получу только тех клиентов, у которых есть заметки, и у меня нет клиентов, у которых нет заметок.

Я знаю, что это длинный запрос и длинный пост, так что, пожалуйста, пингуйте меня, если я могу дать больше информации.

     SELECT QUERY_MAIN.*
,      FORCE_NOTE_CUST.NOTE_CREATION_DATE                                       AS FORCE_ACCEPT_DATE_CUST
,      FORCE_NOTE_GUAR.NOTE_CREATION_DATE                                       AS FORCE_ACCEPT_DATE_GUAR
,      FORCE_NOTE_CUST.ENTERED_BY_NAME                                          AS USER_FORCE_ACCEPT_CUST
,      FORCE_NOTE_GUAR.ENTERED_BY_NAME                                          AS USER_FORCE_ACCEPT_GUAR
,      FORCE_NOTE_CUST.NOTES                                                    AS NOTES_CUST
,      FORCE_NOTE_GUAR.NOTES                                                    AS NOTES_GUAR
FROM (SELECT HP.PARTY_ID
      ,      HCA_CUSTOMER.ACCOUNT_NUMBER                                        AS ACCOUNT_NUMBER
      ,      OKH.CONTRACT_NUMBER                                                AS CONTRACT_NUMBER
      ,      DECODE(OKP.ATTRIBUTE5, 'F', 'Y', 'N')                              AS CUSTOMER_FORCE
      ,      DECODE(GUAR_FORCE.FORCE_FLAG, 'F', 'Y', 'N')                       AS GUARANTOR_FORCE
      --------------------------------------------------------------------------
      FROM  ... customer tables) QUERY_MAIN
--------------------------------------------------------------------------------
, (SELECT* FROM(SELECT JII.PARTY_ID                                             AS PARTY_ID
                ,      TO_CHAR(DECODE( JIHA.ACTION, 'Converted'
                               , SUBSTR(JNV.NOTES_DETAIL,1,2000)
                               , NVL( JNV.NOTES
                                    , SUBSTR( JNV.NOTES_DETAIL
                                            , 1
                                            , 2000))))                          AS NOTES
                ,      JNV.CREATION_DATE                                        AS NOTE_CREATION_DATE
                ,      NVL(PEP.FULL_NAME, FU_INT.USER_NAME)                     AS ENTERED_BY_NAME
                ----------------------------------------------------------------
                FROM    ... notes tables)
   WHERE  NOTES LIKE '%Guarantor acceptance manually progressed%'
   UNION  ALL
   SELECT NULL                                                                  AS PARTY_ID
   ,      NULL                                                                  AS NOTES
   ,      NULL                                                                  AS NOTE_CREATION_DATE
   ,      NULL                                                                  AS ENTERED_BY_NAME
   FROM   DUAL)                                                                 FORCE_NOTE_GUAR
--------------------------------------------------------------------------------
, (SELECT* FROM(SELECT JII.PARTY_ID                                             AS PARTY_ID
                ,      TO_CHAR(DECODE( JIHA.ACTION, 'Converted'
                               , SUBSTR(JNV.NOTES_DETAIL,1,2000)
                               , NVL( JNV.NOTES
                                    , SUBSTR( JNV.NOTES_DETAIL
                                            , 1
                                            , 2000))))                          AS NOTES
                ,      JNV.CREATION_DATE                                        AS NOTE_CREATION_DATE
                ,      NVL(PEP.FULL_NAME, FU_INT.USER_NAME)                     AS ENTERED_BY_NAME
                ----------------------------------------------------------------
                FROM   ... notes tables)
   WHERE  NOTES LIKE '%Customer acceptance manually progressed%'
   UNION  ALL
   SELECT NULL                                                                  AS PARTY_ID
   ,      NULL                                                                  AS NOTES
   ,      NULL                                                                  AS NOTE_CREATION_DATE
   ,      NULL                                                                  AS ENTERED_BY_NAME
   FROM   DUAL)                                                                 FORCE_NOTE_CUST
--------------------------------------------------------------------------------
-- Outer logic to select the appropriate notes
WHERE    1 = 1
AND   (( CUSTOMER_FORCE = 'N' AND FORCE_NOTE_CUST.PARTY_ID IS NULL)
      --If CUSTOMER_FORCE = 'Y'
      --If the customer has force accepted, we need to find the note 
      OR (    CUSTOMER_FORCE = 'Y'
          AND QUERY_MAIN.PARTY_ID              = FORCE_NOTE_CUST.PARTY_ID                      
          AND INSTR(FORCE_NOTE_CUST.NOTES, CONTRACT_NUMBER) > 0))
AND   (( GUARANTOR_FORCE = 'N' AND FORCE_NOTE_GUAR.PARTY_ID IS NULL)
      --If GUARANTOR_FORCE = 'Y'
          --If the guarantor has force accepted, we need to find the note
      OR ( GUARANTOR_FORCE = 'Y' 
          AND QUERY_MAIN.PARTY_ID              = FORCE_NOTE_GUAR.PARTY_ID   
          AND INSTR(FORCE_NOTE_GUAR.NOTES, CONTRACT_NUMBER) > 0));

1 ответ

Решение

Удалить unions с nulls и измените Ваш запрос на left join версия:

SELECT QUERY_MAIN.*,
       FORCE_NOTE_CUST.NOTES,
       FORCE_NOTE_GUAR.NOTES
  FROM QUERY_MAIN
  LEFT JOIN FORCE_NOTE_GUAR on FORCE_NOTE_CUST.PARTY_ID = QUERY_MAIN.PARTY_ID
                           and FORCE_NOTE_CUST.NOTES like '%'||CONTRACT_NUMBER||'%'
  LEFT JOIN FORCE_NOTE_CUST on FORCE_NOTE_GUAR.PARTY_ID = QUERY_MAIN.PARTY_ID
                           and FORCE_NOTE_GUAR.NOTES like '%'||CONTRACT_NUMBER||'%'
Другие вопросы по тегам