2017-02-10 145 views
2

我在優化(應該是)簡單的SQL查詢時遇到了問題,但時間有嚴重問題。我已經寫了三次,但都沒有成功。這是我原本希望能夠工作的一個:INNER JOIN查詢

SELECT RSKADDR.* 
FROM EDW_BASE.RCI_RISK_ADDRESS RSKADDR 
INNER JOIN (
    SELECT DISTINCT COVER_RISK_ID 
    FROM EDW_BASE.RCI_COVER_RISK_MASTER RSKMASTER 
    INNER JOIN 
    (SELECT DISTINCT CONTACT_ID, FOLLOW_UP_DATE 
    FROM EDW_STG.STG_CIM_SVOM03 
    WHERE OUTSTANDING = 1 AND QUEUE = 'CIM Update for Contact Address') ADDR_WF 
    ON RSKMASTER.CONTACT_CODE = ADDR_WF.CONTACT_ID 
    WHERE RSKMASTER.IS_STORNO != 1 
     AND RSKMASTER.PRODUCT_CODE = 'HOME' 
     AND ADDR_WF.FOLLOW_UP_DATE >= RSKMASTER.COVER_EFF_START_DATE 
     AND RSKMASTER.POLICY_STATUS_CODE = 'POLICY' 
     AND ADDR_WF.FOLLOW_UP_DATE <= RSKMASTER.COVER_EFF_END_DATE 
) ACTVRSK 
ON ACTVRSK.COVER_RISK_ID = RSKADDR.RISK_ID 

第一個內部聯接中的代碼一直工作到最後。也就是說,第二個SELECT查詢(在第一個和主SELECT查詢的INNER JOIN查詢中)工作得很快,沒有問題。當我在主SELECT選擇查詢(選擇RSKADDR。*)的INNER JOIN中集成第二個SELECT查詢時出現問題

那麼看起來執行永遠不會結束!

我嘗試過其他的方式和同樣的結果:

SELECT RSKADDR.* 
FROM EDW_BASE.RCI_RISK_ADDRESS RSKADDR 

INNER JOIN EDW_BASE.RCI_COVER_RISK_MASTER RSKMASTER 
ON RSKMASTER.COVER_RISK_ID = RSKADDR.RISK_ID 
    AND RSKMASTER.IS_STORNO != 1 
    AND RSKMASTER.PRODUCT_CODE = 'HOME' 
    AND RSKMASTER.POLICY_STATUS_CODE = 'POLICY' 

INNER JOIN EDW_STG.STG_CIM_SVOM03 ADDR_WF 
ON OUTSTANDING = 1 AND QUEUE = 'CIM Update for Contact Address' 
    AND RSKMASTER.CONTACT_CODE = ADDR_WF.CONTACT_ID 
    AND ADDR_WF.FOLLOW_UP_DATE >= RSKMASTER.COVER_EFF_START_DATE 
    AND ADDR_WF.FOLLOW_UP_DATE <= RSKMASTER.COVER_EFF_END_DATE 

這是荒謬的。這是一個簡單的查詢,不能讓它工作。任何幫助將不勝感激。

+1

你能分享你的模式和數據嗎 –

+0

嗨,謝謝你的迴應。由於涉及隱私信息,遺憾的是無法共享數據。你想知道關於這個計劃的什麼?我能否幫助解釋,而不分享整個模式? – Ankhnesmerira

+0

只能分享示例數據和模式不精確 –

回答

2

DISTINCT是一個代價高昂的操作,很少需要。它通常表示數據庫設計不好或寫得不好。在你的查詢中,你甚至會重複這樣做;那看起來不太好。

第二個查詢看起來好多了。正如你所說的你得到了同樣的結果,DISTINCT在第一個查詢中顯然是多餘的

我看到你在做聯接,但是你選擇的只是一個表中的數據。那麼爲什麼加入呢?從你想要的數據表中選擇,並把你的標準放在它所屬的WHERE

以下查詢可能會更快,因爲它清楚地表明我們只是檢查我們是否在其他表中找到匹配項。但是之後,MySQL被稱爲IN子句的表現不佳,因此可能取決於您使用的版本。

select * 
from edw_base.rci_risk_address 
where risk_id in 
(
    select rm.cover_risk_id 
    from edw_base.rci_cover_risk_master rm 
    where rm.is_storno <> 1 
    and rm.product_code = 'HOME' 
    and rm.policy_status_code = 'POLICY' 
    and exists 
    (
     select * 
     from edw_stg.stg_cim_svom03 adr 
     where adr.contact_id  = rm.contact_code 
     and adr.follow_up_date >= rm.cover_eff_start_date 
     and adr.follow_up_date <= rm.cover_eff_end_date 
     and adr.outstanding = 1 
     and adr.queue = 'CIM Update for Contact Address' 
    ) 
); 

。不管怎麼樣,你的第二個查詢或與我,我想下面的指標將有助於:

create index idx1 on rci_cover_risk_master 
(
    product_code, 
    policy_status_code, 
    is_storno, 
    contact_code, 
    cover_eff_start_date, 
    cover_eff_end_date, 
    cover_risk_id 
); 

create index idx2 on stg_cim_svom03 
(
    contact_id, 
    follow_up_date, 
    outstanding, 
    queue 
); 

create index idx3 on rci_risk_address(risk_id); 
+0

非常感謝您的回覆。你的代碼更有意義,它更清潔。查詢執行仍然花費太長時間,但我認爲這是由於設計錯誤的模式。我想知道我是否應該使用臨時表並對其進行選擇? – Ankhnesmerira

+0

索引不起作用嗎? –

+0

不幸的不是。 :( – Ankhnesmerira

0

從查詢,你只需要RSKADDR數據,因此沒有必要的INNER JOIN。您也可以使用EXISTS關鍵字。嘗試以下查詢

SELECT RSKADDR.* 
FROM EDW_BASE.RCI_RISK_ADDRESS RSKADDR 
WHERE EXISTS (
    SELECT 1 
    FROM EDW_BASE.RCI_COVER_RISK_MASTER RSKMASTER 
    WHERE EXISTS 
    (SELECT 1 
    FROM EDW_STG.STG_CIM_SVOM03 
    WHERE OUTSTANDING = 1 AND QUEUE = 'CIM Update for Contact Address') ADDR_WF 
    AND RSKMASTER.CONTACT_CODE = ADDR_WF.CONTACT_ID 
    AND RSKMASTER.IS_STORNO != 1 
     AND RSKMASTER.PRODUCT_CODE = 'HOME' 
     AND ADDR_WF.FOLLOW_UP_DATE >= RSKMASTER.COVER_EFF_START_DATE 
     AND RSKMASTER.POLICY_STATUS_CODE = 'POLICY' 
     AND ADDR_WF.FOLLOW_UP_DATE <= RSKMASTER.COVER_EFF_END_DATE 
) 
AND RSKMASTER.COVER_RISK_ID = RSKADDR.RISK_ID 
) 

注意:我沒有測試過查詢,因爲沒有可用的模式。

+0

語法錯誤不需要模式 – Strawberry