2016-09-23 4 views
0

Как оптимизировать следующий SQL? Некоторые объединения выполняются без необходимости два раза.Redundant LEFT JOIN - SQL Optimization

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) почти аналогично, за исключением, что у меня есть один дополнительный LEFT JOIN (как отмечено стрелкой). Я попытался создать другую таблицу, заменяющую обычный SQL таблицей, но это не сработало.

+1

Зачем вам оба запроса на всех? Поскольку вы не используете UNION ALL, он удаляет дубликаты, которые делают первый запрос совершенно бессмысленным, потому что каждая строка в этом запросе уже будет во втором запросе. Просто удалите первый запрос, и вы получите тот же результат. –

+0

Почему вы хотите различать оба запроса, UNION по умолчанию отличается от результирующего запроса –

+1

Я согласен с Sean, ваш второй запрос будет содержать все результаты вашего первого запроса, потому что он просто смотрит на дополнительную таблицу, но как LEFT JOIN, поэтому он не будет ограничивать ваши результаты (хорошо, если предполагается, что ваш AND t1.BEID = 100 должен быть WHERE t1.BEID = 100). И я надеюсь, что вам нужны столбцы из всех этих объединений, иначе они будут ездить от них, потому что они не являются изменение набора записей таблицы1 просто добавление к нему, когда есть совпадение – 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 <> '')