2016-09-23 137 views
0

如何優化以下SQL?一些連接不必要地做了兩次。冗餘左連接 - SQL優化

SELECT DISTINCT 
    t1.ID, 
    t1.FirstName, 
    t1.LastName 

FROM Table1 t1 
LEFT JOIN Table2 t2 
    ON t2.LeadID = t1.ID 
LEFT JOIN Table3 t3 
    ON t2.someID = t3.someID 
LEFT JOIN Table4 t4 
    ON t4.UserID = t1.AgentID 
LEFT JOIN Table5 t5 
    ON t5.ProspectID = t1.ProspectID 

WHERE (t1.ID IN (SELECT UserID FROM Users) OR t1.ID IS NULL) 
AND t1.BEID = 100 
AND t1.LastName <> '' 
AND t1.FirstName <> '' 


UNION 


SELECT DISTINCT 
    t1.ID, 
    t1.FirstName, 
    t1.LastName 

FROM Table1 t1 
LEFT JOIN Table2 t2 
    ON t2.LeadID = t1.ID 
LEFT JOIN Table3 t3 
    ON t2.someID = t3.someID 
LEFT JOIN Table4 t4 
    ON t4.UserID = t1.AgentID 
LEFT JOIN Table5 t5 
    ON t5.ProspectID = t1.ProspectID 
LEFT JOIN QueueMap uq 
    ON uq.QueueID = t1.agentID --<--- this is additional JOIN 
    AND uq.QueueID IN (SELECT QueueID FROM UserQueues) 
    AND t1.LastName <> '' 
    AND t1.FirstName <> ' 

的SQL(UNION後)的第二部分是不同的是我有一個附加左連接(如標註的箭頭)幾乎相同。我已經嘗試創建另一個表,用表替換普通的SQL,但它不起作用。

+1

爲什麼你需要在所有的這兩個查詢?由於您沒有使用UNION ALL,因此它將刪除重複項,因爲該查詢中的每一行都已經存在於第二個查詢中,因此重複項將使第一個查詢完全無意義。只要刪除第一個查詢,你應該得到完全相同的結果。 –

+0

爲什麼你想在兩個查詢上都有不同,默認情況下UNION對結果查詢有不同的區別 –

+1

我同意Sean的第二個查詢將包含你的第一個查詢的所有結果,因爲它只是查看一個額外的表,但是作爲一個LEFT加入,所以它不會限制你的結果(當然假設你的AND t1.BEID = 100應該是WHERE t1.BEID = 100)我希望你想要所有這些連接的列,否則就不要騎它們,因爲它們不是更改Table1的記錄集,只是在匹配時添加它 – Matt

回答

0
SELECT DISTINCT 
    t1.ID, 
    t1.FirstName, 
    t1.LastName 

FROM Table1 t1 
LEFT JOIN Table2 t2 
    ON t2.LeadID = t1.ID 
LEFT JOIN Table3 t3 
    ON t2.someID = t3.someID 
LEFT JOIN Table4 t4 
    ON t4.UserID = t1.AgentID 
LEFT JOIN Table5 t5 
    ON t5.ProspectID = t1.ProspectID 
LEFT JOIN QueueMap uq 
    ON uq.QueueID = t1.agentID --<--- this is additional JOIN 
    AND uq.QueueID IN (SELECT QueueID FROM UserQueues) 
    AND t1.LastName <> '' 
    AND t1.FirstName <> '' 
WHERE 
    ((t1.ID IN (SELECT UserID FROM Users) OR t1.ID IS NULL) 
    AND t1.BEID = 100 
    AND t1.LastName <> '' 
    AND t1.FirstName <> '') 

    OR uq.QueueID IS NOT NULL 

我的猜測是,你可能不需要一些的聯接和,而不是使用IN(SELECT),你可能需要連接到UserQueues和用戶表,但如果你把你有什麼上面,你可以結合通過簡單地增加一個或者像我所做的那樣在沒有UNION的情況下得到相同的結果。

0
  1. 我認爲你不需要獨特的,因爲你使用的是聯盟而不是聯盟。

  2. 由於在大多數情況下不需要掃描所有頁面,存在通常會更快地進行搜索。

所以,我的第一次嘗試是類似的東西:

SELECT 
    t1.ID, 
    t1.FirstName, 
    t1.LastName 
FROM 
    Table1 t1 
    LEFT JOIN Table2 t2 ON t2.LeadID = t1.ID 
    LEFT JOIN Table3 t3 ON t3.someID = t2.someID 
    LEFT JOIN Table4 t4 ON t4.UserID = t1.AgentID 
    LEFT JOIN Table5 t5 ON t5.ProspectID = t1.ProspectID 
WHERE 
    ((EXISTS (SELECT 1 FROM Users where UserID = t1.ID)) 
     OR (t1.ID IS NULL) 
    ) 
    AND (t1.BEID = 100) 
    AND (t1.LastName <> '') 
    AND (t1.FirstName <> '') 


UNION 


SELECT 
    t1.ID, 
    t1.FirstName, 
    t1.LastName 

FROM 
    Table1 t1 
    LEFT JOIN Table2 t2 ON t2.LeadID = t1.ID 
    LEFT JOIN Table3 t3 ON t3.someID = t2.someID 
    LEFT JOIN Table4 t4 ON t4.UserID = t1.AgentID 
    LEFT JOIN Table5 t5 ON t5.ProspectID = t1.ProspectID 
    LEFT JOIN QueueMap uq ON uq.QueueID = t1.agentID --<--- this is additional JOIN 
          AND (EXISTS (SELECT 1 FROM UserQueues WHERE QueueID = uq.QueueID)) 
          AND (t1.LastName <> '') 
          AND (t1.FirstName <> '')