2016-09-23 59 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 <> '')