请慢慢阅读。这不是重复。
表:
CREATE TABLE [dbo].[TEST] (
[TEST_ID] [integer] IDENTITY (1, 1) NOT NULL ,
....
[TEST_TYPE_ID] [char](1) NULL ,
....
)
CREATE TABLE [dbo].[TEST_A] (
[TEST_ID] [integer] NOT NULL ,
....
)
CREATE TABLE [dbo].[TEST_B] (
[TEST_ID] [integer] NOT NULL ,
....
)
通常你会写:
select *
from dbo.TEST as t
left join dbo.TEST_A as ta on ta.TEST_ID = t.TEST_ID
left join dbo.TEST_B as tb on tb.TEST_ID = t.TEST_ID
...
然而,Sql Server可以节省大量工作 - 如果它知道只有一些表TEST的行可能加入TEST_A:
select *
from dbo.TEST as t
left join dbo.TEST_A as ta on t.TEST_TYPE_ID = 'A'
and ta.TEST_ID = t.TEST_ID
left join dbo.TEST_B as tb on t.TEST_TYPE_ID = 'B'
and tb.TEST_ID = t.TEST_ID
...
这些查询返回完全相同的结果。添加TEST_TYPE_ID = X不会更改结果。 注意:您可以在where语句中对TEST_TYPE_ID进行限制。这会改变返回的行数。
我的问题是:如果在右侧放置限制,在左连接中,Sql Server是否会首先使用此信息?这里的操作顺序非常重要。当TEST和TEST_A很大,但只有少数记录加入时,这很重要。
我测试了这个,执行计划似乎表明:没有。看来Sql Server首先执行正常的左连接尝试将TEST中的所有记录连接到TEST_A,然后它应用"过滤器"。但是,我不确定我是否正确阅读了执行计划。如果第二次应用TEST_TYPE_ID = X,那么它实际上是无操作。如果首先应用TEST_TYPE_ID = X,则会将左连接限制为仅实际连接的行。
注意:我的实际案例看起来非常不同。我已经将问题提炼到这个简单的例子来证明这个问题。