SQL Server 2008 R2,但在所有其他版本的 SQL Server 上也发现了可能的行为。
这似乎很明显,但对我来说,这似乎是一个错误。
以下查询给出了意想不到的结果,这是设置:
CREATE TABLE #Base (
Key1 int,
RefDate date
)
CREATE TABLE #JoinTable (
Key1 int,
RefDate date
)
INSERT INTO #Base
SELECT 1, '2012-05-05'
UNION
SELECT 2, '2013-06-06'
UNION
SELECT 3, '2014-07-07'
UNION
SELECT 4, '2015-08-08'
UNION
SELECT 5, '2016-09-09'
INSERT INTO #JoinTable
SELECT 4, '2012-05-05'
UNION
SELECT 5, '2013-06-06'
UNION
SELECT 6, '2014-07-07'
UNION
SELECT 7, '2015-08-08'
UNION
SELECT 8, '2016-09-09'
Run Code Online (Sandbox Code Playgroud)
以下查询按我的预期执行,返回仅出现在基表中的 3 行:
SELECT *
FROM #Base b
LEFT OUTER JOIN #JoinTable j ON b.Key1 = j.Key1
WHERE j.Key1 IS NULL
Run Code Online (Sandbox Code Playgroud)
现在我想将行限制为 2014 年 1 月 1 日之前的行。据我所知,我可以采用以下两种方法,两者都应该是完全可行的:
SELECT b.*
FROM #Base b
LEFT OUTER JOIN #JoinTable j ON b.Key1 = j.Key1 AND b.RefDate < '2014-01-01'
WHERE j.Key1 IS NULL
SELECT b.*
FROM #Base b
LEFT OUTER JOIN #JoinTable j ON b.Key1 = j.Key1
WHERE j.Key1 IS NULL AND b.RefDate < '2014-01-01'
Run Code Online (Sandbox Code Playgroud)
但是,只有第二个查询返回我想要的数据。第一个似乎忽略了连接行中 AND 之后添加的连接条件。
为什么?
(sql小提琴链接在这里)
这不是一个错误,它是如何LEFT JOIN
工作的。
b LEFT JOIN j ON <SomeCondition>
Run Code Online (Sandbox Code Playgroud)
b
无论连接条件如何,都将返回所有行。连接条件仅定义/限制将从中返回的行j
。
SELECT b.*
FROM #Base b
LEFT OUTER JOIN #JoinTable j ON b.Key1 = j.Key1 AND b.RefDate < '2014-01-01'
WHERE j.Key1 IS NULL
Run Code Online (Sandbox Code Playgroud)
你可以这样想:
#Base
.#Base
查找#JoinTable
满足连接条件 ( b.Key1 = j.Key1 AND b.RefDate < '2014-01-01'
) 的所有行。中可能没有这样的行#JoinTable
,在这种情况下返回NULLs
。请注意,连接条件不过滤#Base
,它只过滤#JoinTable
。当你把b.RefDate < '2014-01-01'
进入WHERE
,那么你过滤#Base
。
归档时间: |
|
查看次数: |
1105 次 |
最近记录: |