在尝试外连接数据时,带有NULL的Oracle SQL UNION ALL会导致性能问题

时间:2017-09-22 12:22:35

标签: sql oracle oracle-ebs

我正在尝试构建一个从Oracle返回客户及其注释的查询。不幸的是,我从中选择数据的注释表与客户没有任何1-1连接,所以我通过使用聚会ID并在包含客户合同号的注释中查找特定字符串来加入数据。

我想要做的是,如果票据存在且票据不存在,则退还客户,合约及其票据信息。

我知道下面的代码是冗长的,但我对如何处理代码的最后一位特别感兴趣(所以我最后加入了注释信息的代码)。我在当前版本的查询中遇到的问题是,如果我通过添加带有空值的UNION ALL加入FORCE_NOTE_GUAR和FORCE_NOTE_CUST子查询,则性能非常糟糕。

如果我删除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 个答案:

答案 0 :(得分:3)

使用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||'%'