联接条件或where子句中的SQL筛选条件哪个更有效

联接条件或where子句中的SQL筛选条件哪个更有效,sql,sql-server,join,where-clause,Sql,Sql Server,Join,Where Clause,我有一个连接两个表的相对简单的查询。Where条件可以在联接条件中表示,也可以表示为Where子句。我想知道哪个更有效 查询是查找销售人员从开始到晋升的最大销售额 案例1 select salesman.salesmanid, max(sales.quantity) from salesman inner join sales on salesman.salesmanid =sales.salesmanid and sales.salesdate <

我有一个连接两个表的相对简单的查询。Where条件可以在联接条件中表示,也可以表示为Where子句。我想知道哪个更有效

查询是查找销售人员从开始到晋升的最大销售额

案例1

select salesman.salesmanid, max(sales.quantity)
from salesman
inner join sales  on salesman.salesmanid =sales.salesmanid 
                  and sales.salesdate < salesman.promotiondate
group by salesman.salesmanid 
案例2

select salesman.salesmanid, max(sales.quantity)
from salesman
inner join sales  on salesman.salesmanid =sales.salesmanid 
where sales.salesdate < salesman.promotiondate
group by salesman.salesmanid 
注意:案例1缺少一个where子句

RDBMS是SQLServer2005

编辑
如果连接条件或where子句的第二部分是sales.salesdate<某个固定日期,那么实际上连接两个表的任何条件都不会改变答案。

这可能看起来有些轻率,但答案是查询分析器生成最有效计划的查询


在我看来,它们似乎是等价的,因此查询分析器可能会生成完全相同的计划,但您必须进行测试。

我不会将性能作为决定因素——老实说,我不认为这两种情况之间有任何可测量的性能差异,真的

我总是使用案例2——为什么?因为在我看来,您应该只将在两个表之间建立连接的实际条件放在JOIN子句中—其他所有内容都属于WHERE子句

在我看来,这只是一个保持事物清洁并把它们放在它们该放的地方的问题

显然,对于左外部联接的情况,条件的放置确实会对返回的结果产生影响——当然,这些情况将被排除在我的建议之外


Marc

两者都不是更有效的方法,使用WHERE方法被认为是旧方法。你可以看看执行计划,看到他们做同样的事情。

我不认为你会找到一个适用于所有情况的有限答案。2并不总是可互换的-因为对于某些查询,一些左连接将通过将条件放置在WHERE和FROM行中得到不同的结果

在您的情况下,您应该评估这两个查询。在SSMS中,您可以查看这两个查询的估计执行计划和实际执行计划—这将是确定哪一个更为优化的良好第一步。您还可以查看每个设置统计信息time on、set statistics IO on的时间和IO,这也将为您提供做出决策的信息

对于您问题中的查询,我敢打赌,它们都会产生相同的查询计划,因此在这种情况下,这可能无关紧要,但在其他情况下,可能会产生不同的计划

试试这个,看看这两个

SET STATISTICS IO ON
SET STATISTICS TIME ON

select salesman.salesmanid, 
       max(sales.quantity)
from   salesmaninner join sales on salesman.salesmanid =sales.salesmanid
       and sales.salesdate < salesman.promotiondate
group by salesman.salesmanid

select salesman.salesmanid, 
       max(sales.quantity)
from   salesmaninner join sales on salesman.salesmanid = sales.salesmanid 
where  sales.salesdate < salesman.promotiondate
group by salesman.salesmanid

SET STATISTICS TIME OFF
SET STATISTICS IO OFF

您可以运行执行计划估计器和sql探查器,查看它们是如何相互叠加的

但是,根据此SQL Server MVP,它们在语义上是相同的:


熟悉SQL Management Studio中的估计执行计划!!正如其他人所说,无论你做什么,你都要受分析器的摆布,所以相信它的估计。我猜你提供的两个会产生完全相同的计划

如果这是一种试图改变发展文化的尝试,那么选择一种能为你提供更好计划的文化;对于相同的,遵循文化


我已经在其他类似的效率帖子上对此发表了评论,这既真诚又讽刺——如果这是你的瓶颈所在,那么向你和你的团队敬礼。

我更喜欢在加入时有任何硬编码的标准。它使SQL更具可读性和可移植性

可读性: 您可以确切地看到将要获得的数据,因为所有表条件都写在联接中。在大型语句中,标准可能隐藏在50个其他表达式中,很容易被忽略

便携性: 您可以从FROM子句中复制一个块,然后将其粘贴到其他地方。这就给出了连接和任何需要的条件。如果在联接这两个表时始终使用该条件,那么将其放入联接中是最合乎逻辑的

例如:

FROM
table1 t1
JOIN table2 t2_ABC ON
  t1.c1 = t2_ABC.c1 AND
  t2_ABC.c2 = 'ABC'
如果您需要从表2中获得第二列,只需将该块复制到记事本中,搜索/重新拼贴ABC和presto,并将整个新代码块粘贴回

其他: 在内部联接和外部联接之间进行更改也更容易,而不必担心WHERE子句中可能出现的任何条件

在可能的情况下,我将WHERE子句严格保留为运行时标准

至于效率: 如果你指的是执行速度,那么正如其他人所说,它是多余的。
如果您指的是更简单的调试和重用,那么我更喜欢选项1。

在此之前,我最后想说一件事,我已经通知您了。。 这两种方法可能会提供相同的性能,或者使用Where子句的标准可能会比一些答案中的更快一些

但我发现了一个区别,y 您可以根据您的逻辑需要使用

使用条件at ON子句不会筛选/跳过要选择的行,相反,根据条件,联接列将为null

使用条件at Where子句可以过滤/跳过整个结果中的行



连接中的案例1标准更适合封装,增加封装通常是一件好事:减少对另一个查询的复制/粘贴遗漏,减少以后转换为左连接时的错误,增加与可读性相关的内容,减少WHERE子句中的噪音。在本例中,WHERE子句仅捕获主表条件或跨多个表的条件。

实际测试这些查询所用的时间有什么问题?因为查询已缓存,但非常感谢,really@Gratzy-DBCC FREEPROCCACHE@Gratzy-就为了让你明白这一点。有一本专门针对SQL Server 2000的书,它可能会达到您想要的深度—不确定2005版—我们正在基于存储过程参数的值在联合中执行一条SQL语句。目前,SQL测试where子句中的参数值。对内部连接进行测试是否更好?我认为探索一下这是否是一个用法很重要的场合可能会有用?join和where有单独的引用,但没有讨论先执行哪一个?我的示例不是最好的将join和/或where子句的第二部分更改为固定日期,而不是SALESSER表中的日期。啊,好吧,不管是哪种情况,执行计划都是您的朋友。分析它,找出哪一个性能最好。我敢打赌它们是相同的。这将是具体的内部joinsGratzy-在这种情况下,我同意marc_s-过滤条件应该保留在查询的WHERE部分,而连接条件应该保留在查询的FROM部分。WHERE criteria表有很多很多行是否重要。我知道这听起来可能很琐碎,但我想知道是否最好将其作为连接标准的一部分,而不是clauseI认为这不会产生任何影响的部分-但我仍然建议查看为这两个查询生成的计划。一般来说,我认为如果将过滤器和联接条件分开,代码将更容易阅读。在实践中,这可能并不总是可能的——但如果有相同的查询计划,我总是选择第二个查询以确保可读性。是的,我熟悉估计的执行计划。但是,它不会告诉我为什么它会以这种方式生成执行计划。我想知道为什么一个可能比另一个更有效。@Gratzy:IMO有人可能会说案例1更适合封装在这种情况下,其中子句只用于主表条件。总而言之,联接中的条件更适合封装,增加封装通常更好。链接断开了。答案是8年前的,所以我不太惊讶。性能问题的答案仍然是它们是相同的。然而,@marc_在他的回答中写道,连接语法一直是清晰的标准。保留非联接条件的where子句。