Oracle SQL UNION ALL with NULL在尝试外部联接数据时会导致性能问题

Oracle SQL UNION ALL with NULL在尝试外部联接数据时会导致性能问题,sql,oracle,oracle-ebs,Sql,Oracle,Oracle Ebs,我试图构建一个查询,返回Oracle的客户及其笔记。不幸的是,我从中选择数据的notes表与客户没有任何1-1联接,因此我使用party id并在包含客户合同号的notes中查找特定字符串来联接数据 我想做的是返回客户、合同和他们的注释信息(如果注释存在或不存在) 我知道下面的代码很长,但我特别感兴趣的是如何处理代码的最后一部分(因此我在最后加入notes信息的代码)。我在查询的当前版本中遇到的问题是,如果我通过添加带有null的UNION ALL来加入FORCE_NOTE_GUAR和FORCE

我试图构建一个查询,返回Oracle的客户及其笔记。不幸的是,我从中选择数据的notes表与客户没有任何1-1联接,因此我使用party id并在包含客户合同号的notes中查找特定字符串来联接数据

我想做的是返回客户、合同和他们的注释信息(如果注释存在或不存在)

我知道下面的代码很长,但我特别感兴趣的是如何处理代码的最后一部分(因此我在最后加入notes信息的代码)。我在查询的当前版本中遇到的问题是,如果我通过添加带有null的UNION ALL来加入FORCE_NOTE_GUAR和FORCE_NOTE_CUST子查询,那么性能会非常差

如果我删除该联合,所有性能都很好,但是我只得到有注释的客户,没有没有没有注释的客户

我知道这是一个很长的查询和一个很长的职位,所以请平我,如果我可以提供更多的信息

     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));

使用
nulls
删除
联合
,并将查询更改为
左联合
版本:

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

使用
nulls
删除
联合
,并将查询更改为
左联合
版本:

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

我相信你可以(至少)从中删掉很多不相关的栏目,让人们更容易相处?@TonyAndrews好观点。我相信你可以(至少)删掉很多不相关的栏目,让人们更容易相处?@TonyAndrews好观点。是的,这个问题是一个很好的例子,说明了为什么旧的连接语法被弃用而支持ANSI连接。对于外部联接,ANSI样式更易于阅读和理解。谢谢!我最初考虑使用左连接,但与和/或过于复杂了……是的,这个问题是一个很好的例子,说明了为什么旧连接语法被弃用而支持ANSI连接。对于外部联接,ANSI样式更易于阅读和理解。谢谢!我最初考虑使用左连接,但由于和/或。。。