Является ли наличие ИЛИ в состоянии ВНУТРЕННЕГО СОЕДИНЕНИЯ плохой идеей? - PullRequest
88 голосов
/ 05 мая 2011

Пытаясь повысить скорость чрезвычайно медленного запроса (несколько минут для двух таблиц с ~ 50 000 строк в каждой, в SQL Server 2008, если это имеет значение), я сузил проблему до OR в моем внутреннем соединении, как в:

SELECT mt.ID, mt.ParentID, ot.MasterID
  FROM dbo.MainTable AS mt
  INNER JOIN dbo.OtherTable AS ot ON ot.ParentID = mt.ID
                                  OR ot.ID = mt.ParentID

Я изменил это на (я надеюсь, что это) эквивалентную пару левых соединений, показанную здесь:

SELECT mt.ID, mt.ParentID,
   CASE WHEN ot1.MasterID IS NOT NULL THEN
      ot1.MasterID ELSE
      ot2.MasterID END AS MasterID
  FROM dbo.MainTable AS mt
  LEFT JOIN dbo.OtherTable AS ot1 ON ot1.ParentID = mt.ID
  LEFT JOIN dbo.OtherTable AS ot2 ON ot2.ID = mt.ParentID
  WHERE ot1.MasterID IS NOT NULL OR ot2.MasterID IS NOT NULL

.. и запрос теперь выполняется примерно за секунду!

Является ли вообще плохой идеей ставить OR в состояние соединения? Или мне просто как-то не повезло в раскладке моих столов?

Ответы [ 3 ]

103 голосов
/ 05 мая 2011

Этот тип JOIN нельзя оптимизировать до HASH JOIN или MERGE JOIN.

Это можно выразить как объединение двух наборов результатов:

SELECT  *
FROM    maintable m
JOIN    othertable o
ON      o.parentId = m.id
UNION
SELECT  *
FROM    maintable m
JOIN    othertable o
ON      o.id = m.parentId

, каждый из которых является эквиджоин, однако оптимизатор SQL Server недостаточно умен, чтобы увидеть его в написанном вами запросе (хотя они логически эквивалентны).

2 голосов
/ 21 декабря 2017

Я использую следующий код для получения другого результата от условия Это сработало для меня.


Select A.column, B.column
FROM TABLE1 A
INNER JOIN
TABLE2 B
ON A.Id = (case when (your condition) then b.Id else (something) END)
0 голосов
/ 21 января 2019

Вместо этого вы можете использовать UNION ALL.

SELECT mt.ID, mt.ParentID, ot.MasterID FROM dbo.MainTable AS mt Union ALL SELECT mt.ID, mt.ParentID, ot.MasterID FROM dbo.OtherTable AS ot

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...