2017-09-22 7 views
0

Oracle 및 해당 노트에서 고객을 반환하는 쿼리를 작성하려고합니다. 불행하게도 데이터를 선택하는 노트 테이블에는 고객과 1-1 조인이 없으므로 파티 ID를 사용하고 고객 계약 번호가 포함 된 노트의 특정 문자열을 찾는 방식으로 데이터에 합류합니다.Oracle SQL UNION ALL - NULL을 사용하면 데이터 외부 조인을 시도 할 때 성능 문제가 발생합니다.

내가 원하는 것은 메모가 존재하고 메모가없는 경우 고객, 계약서 및 메모 정보를 반환하는 것입니다.

나는 아래의 코드가 길다는 것을 알고 있지만 특히 코드의 마지막 비트를 처리하는 방법에 관심이 있습니다. (결국 노트 정보와 함께 코드를 처리합니다.) 현재 버전의 쿼리에있는 문제는 NULL로 UNION ALL을 추가하여 FORCE_NOTE_GUAR 및 FORCE_NOTE_CUST 하위 쿼리에 참여하면 성능이 매우 나쁘다는 것입니다.

해당 유니온을 모두 제거하면 성능은 좋지만 필자는 노트를 가지고있는 고객 만 얻고 메모가없는 고객은 얻지 못합니다.

긴 쿼리와 긴 게시물이므로 자세한 정보를 제공 할 수 있다면 ping 해주시기 바랍니다.

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

나는 당신이 사람들에게 간단하게 뭔가를주고 그에서 (적어도) 관련없는 열을 많이 줄일 수 확신 작업? –

+0

@TonyAndrews 좋은 지적. – Ucello

답변

3

nullsunions를 제거하고 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||'%' 
+0

예,이 질문은 ANSI 조인을 위해 이전 조인 구문이 사용되지 않는 이유의 좋은 예입니다. 외부 조인의 경우 ANSI 스타일은 읽고 이해하기가 훨씬 쉽습니다. – kfinity

+0

감사합니다! 처음에는 왼쪽 조인을 사용했지만 AND/OR로는 복잡하게 생각했습니다 ... – Ucello