在WHERE子句中使用OR时,从LEFT JOIN中消除了行

时间:2018-12-28 09:22:22

标签: sql sql-server tsql left-join

我遇到了一个SQL脚本问题,我对LEFT JOIN的理解无法解释。我实际上已经确定并解决了这个问题,但是想了解为什么下面的“断开连接”版本不起作用。

CREATE TABLE #LeftTable
(RunID BIGINT,PolicyRef NVARCHAR(MAX),Val NVARCHAR(MAX))

INSERT INTO #LeftTable
VALUES (100,'pol1','hi'),(100,'pol2','hi2'),(100,'pol3','hi3')

CREATE TABLE #RightTable
(RunID BIGINT,PolicyRef NVARCHAR(MAX),Assured NVARCHAR(MAX))

INSERT INTO #RightTable
VALUES (80,'pol1','celec'),(90,'pol2','colorado'),(100,'pol2','colorado')

--SELECT * FROM #LeftTable
--SELECT * FROM #RightTable

-- Proper Join
SELECT *
FROM #LeftTable lt
LEFT OUTER JOIN #RightTable rt ON lt.PolicyRef = rt.PolicyRef AND lt.RunID = rt.RunID

-- Broken Join (eliminates Pol1 from LeftTable)
SELECT *
FROM #LeftTable lt
LEFT OUTER JOIN #RightTable rt ON lt.PolicyRef = rt.PolicyRef
WHERE lt.RunID = rt.RunID OR rt.runid IS NULL

DROP TABLE #LeftTable
DROP TABLE #RightTable

我希望两个查询返回相同的内容,但查询2中消除了pol1行。我认为这是因为存在pol1的记录,其中RunID不是我们需要的RunID。但是我不明白为什么要删除该行。

3 个答案:

答案 0 :(得分:4)

在此查询中:

SELECT *
FROM #LeftTable lt
LEFT OUTER JOIN #RightTable rt ON lt.PolicyRef = rt.PolicyRef
WHERE lt.RunID = rt.RunID OR rt.runid IS NULL

这部分

SELECT *
FROM #LeftTable lt
LEFT OUTER JOIN #RightTable rt ON lt.PolicyRef = rt.PolicyRef

将给您3个结果:

  

100,'pol1','hi',80,'pol1','celec'

     

100,'pol2','hi2',90,'pol2','科罗拉多'

     

100,'pol2','hi2',100,'pol2','科罗拉多'

但是where语句希望该结果集具有相同的id,因此这是唯一可能的结果:

  

100,'pol2','hi2',100,'pol2','colorado'

答案 1 :(得分:1)

为此,您需要写and来代替如下所示的位置

-- Broken Join (eliminates Pol1 from LeftTable)
SELECT *
FROM #LeftTable lt
LEFT OUTER JOIN #RightTable rt ON lt.PolicyRef = rt.PolicyRef
AND lt.RunID = rt.RunID OR rt.runid IS NULL

答案 2 :(得分:1)

这是预期的行为... 首先要了解的是,这些查询在逻辑上不是等效的...您在第二个查询中看到“ pol1”行被过滤掉的原因很简单。 rt.RunID既不等于lt.RunID,也不为NULL ...其值为“ 80”,因此不满足任何OR条件。