2

我遇到了一个 SQL 脚本问题,我无法用我对 LEFT JOIN 的理解来解释。我实际上已经确定并解决了这个问题,但想了解为什么下面的 Broken 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。但我不明白为什么应该消除这一行。

4

3 回答 3

3

在这个查询中:

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','科罗拉多'

于 2018-12-28T09:30:07.903 回答
1

为此,您需要写and在 where 的位置,如下所示

-- 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
于 2018-12-28T09:31:03.280 回答
1

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

于 2018-12-28T09:48:48.620 回答