我遇到了一个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。但是我不明白为什么要删除该行。
答案 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条件。