INNER JOIN条件中的'OR'是个坏主意吗?

lad*_*dge 89 sql t-sql sql-server inner-join sql-server-2008

在尝试提高极慢查询的速度时(在两个表上只有几万分钟,在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
Run Code Online (Sandbox Code Playgroud)

我把它更改为(我希望是)一对等效的左连接,如下所示:

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
Run Code Online (Sandbox Code Playgroud)

..现在查询运行大约一秒钟!

OR加入条件通常是个坏主意吗?或者我在桌子的布局中不知何故不幸?

Qua*_*noi 105

这种JOIN对a HASH JOIN或a 是不可优化的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
Run Code Online (Sandbox Code Playgroud)

,然而,每个都是等值连接,但是,SQL Server优化器不够智能,无法在你编写的查询中看到它(尽管它们在逻辑上是等价的).

  • 这很有道理,谢谢.我仍然不确定我的查询是否有特殊的东西,或者我是否应该完全避免连接`ON w = x OR y = z`模式? (3认同)
  • @ladenedge:可能有其他条件可以帮助`SQL Server`理解需要连接.比如说,查询`SELECT*FROM othertable WHERE parentId = 1 OR id = 2`将使用连接,如果两个字段都被索引,那么理论上没有什么可以阻止在循环中做同样的事情."SQL Server"是否会实际构建这个计划,取决于很多因素,但我从未见过它是在现实生活中构建的. (3认同)

小智 7

我使用以下代码从对我有用的条件中获得不同的结果。


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)
Run Code Online (Sandbox Code Playgroud)