在 from 子句或 where 子句中进行 equi join 是不是更好

Posted

技术标签:

【中文标题】在 from 子句或 where 子句中进行 equi join 是不是更好【英文标题】:Is it better to do an equi join in the from clause or where clause在 from 子句或 where 子句中进行 equi join 是否更好 【发布时间】:2011-06-09 07:40:41 【问题描述】:

当在主键列上连接两个简单表并放置一个加法相等条件时,这可以在连接本身或 where 子句中完成。

例如以下是等价的。 我的问题是 - 有什么理由使用一种风格而不是另一种风格?

SELECT * 
FROM A
INNER JOIN B ON A.A_ID = B.A_ID
            AND A.DURATION = 3.00

...对比:

SELECT * 
FROM A
INNER JOIN B ON A.A_ID = B.A_ID
WHERE A.DURATION = 3.00

【问题讨论】:

我想对于更复杂的查询,它将连接和任何条件保持在同一个地方,这避免了查询部分之间的滚动 【参考方案1】:

一般来说,它没有语义上的区别。

虽然有一种极端情况可以做到。如果将(已弃用)GROUP BY ALL 构造添加到查询中,如下所示。

DECLARE @A TABLE(A_ID INT, DURATION DECIMAL(3,2) )
INSERT INTO @A VALUES(1,2.00)

DECLARE @B TABLE(A_ID INT)
INSERT INTO @B VALUES(1)

/*Returns one row*/
SELECT *
FROM @A A
INNER JOIN @B B ON A.A_ID = B.A_ID
WHERE A.DURATION = 3.00
GROUP BY ALL A.A_ID, A.DURATION, B.A_ID

/*Returns zero rows*/    
SELECT *
FROM @A A
INNER JOIN @B B ON A.A_ID = B.A_ID  AND A.DURATION = 3.00
GROUP BY ALL A.A_ID, A.DURATION, B.A_ID

【讨论】:

【参考方案2】:

这是一个风格问题。通常,您希望将定义结果集“形状”的条件放在 FROM 子句中(即控制每个表中的哪些行应该连接在一起以产生结果的条件),而 filter 结果集应该在 WHERE 子句中。对于INNER JOIN,效果是一样的,但是一旦涉及到OUTER JOIN(LEFT,RIGHT),感觉就清晰了很多。


在您的第一个示例中,我想问“这与表 B 有什么关系?”当我在 JOIN 中遇到这种奇怪的情况时。而在第二个中,如果我不感兴趣,我可以跳过 FROM 子句(和所有 JOIN),只查看确定行是否将在 WHERE 子句中返回的条件。

【讨论】:

【参考方案3】:

重要的是 JOIN 的类型。 没有区别,提供的任何一个查询版本都将使用相同的执行计划,因为您正在处理 INNER JOIN。

如果处理 OUTER JOIN(即:LEFT、RIGHT),则两个版本之间存在巨大差异,因为应用了WHERE 标准加入之后。如果在ON 子句中指定了条件,则在之前应用该条件,这会在结果集之间产生相当大的差异。

【讨论】:

【参考方案4】:

对于 SQL Server 2000+,每个查询的查询计划将是相同的,因此性能也是如此。

您可以通过使用 SSMS 来验证这一点,以在执行查询之前显示每个按 CTRL+M 的查询的实际执行计划。结果窗格将有一个显示执行计划的附加选项卡。您会看到,在这种情况下,两个计划是相同的。

【讨论】:

【参考方案5】:

这是风格问题。优化器会尽力而为。

【讨论】:

【参考方案6】:
    --Samples for time of join wheather can we write condition at where or ON 
create table #emp(id int ,teamid int)
create table #team(tid int,name char(2))
insert into #emp values(1,1)
insert into #emp values(2,1)
insert into #emp values(3,2)
insert into #emp values(4,0)

insert into #team values(1,'A')
insert into #team values(2,'B')
insert into #team values(3,'C')

--select * from #emp
--select * from #team

--on inner join => there is no difference in Query Exc. Plan
--select * from #emp e join #team t on e.teamid=t.tid where e.teamid=2
--select * from #emp e join #team t on e.teamid=t.tid and e.teamid=2


/*on outetr join see the differnence If dealing with an OUTER JOIN (IE: LEFT, RIGHT), 
there is a huge difference between the two versions because the WHERE criteria is applied after the JOIN is made. 
If the criteria is specified in the ON clause, the criteria is applied before the JOIN is made which can made a considerable difference 
between the result sets.*/
select * from #emp e left join #team t on e.teamid=t.tid
select * from #emp e left join #team t on e.teamid=t.tid where e.teamid=2
select * from #emp e left join #team t on e.teamid=t.tid and  (e.teamid=2 or t.tid=1) and t.name='A'


drop table #emp
drop table #team

【讨论】:

请看下面的详细说明,帮助您快速掌握事情 我没有看到解释。只是重复 OMG Ponies 两年前所说的话。

以上是关于在 from 子句或 where 子句中进行 equi join 是不是更好的主要内容,如果未能解决你的问题,请参考以下文章

简述SELECT语句中的FROM、WHERE以及ORDER BY子句的作用。SQL Server

在 from 子句 *and* where 子句中添加连接条件使查询更快。为啥?

使用Having子句

[MySQL] 过滤数据

CAML 查询过滤 where 子句

在 Oracle 查询中将连接从 Where 子句移动到 From 子句