连接条件中的SQL筛选条件或更高效的where子句

时间:2009-09-09 20:26:06

标签: 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 < 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是Sql Server 2005

修改 如果第二部分连接条件或where子句是sales.salesdate&lt;一些固定的日期,所以实际上没有任何加入这两个表的标准会改变答案。

9 个答案:

答案 0 :(得分:27)

我不会在这里使用性能作为决定因素 - 老实说,我认为这两种情况之间没有任何可衡量的性能差异,实际上。

我会一直使用案例#2 - 为什么?因为在我看来,你应该只将在两个表之间建立JOIN的实际标准放入JOIN子句中 - 其他一切都属于WHERE子句。

只需要保持清洁,把东西放在他们所属的地方,IMO。

显然,有些LEFT OUTER JOIN的情况下,标准的放置确实会对返回的结果产生影响 - 当然,这些情况会从我的建议中排除。

马克

答案 1 :(得分:3)

您可以运行执行计划估算器和sql探查器来查看它们如何相互叠加。

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

http://www.eggheadcafe.com/conversation.aspx?messageid=29145383&threadid=29145379

答案 2 :(得分:3)

我更喜欢在连接中使用任何硬编码标准。它使SQL更具可读性和可移植性。

可读性: 您可以准确地看到要获取的数据,因为所有表标准都是在连接中写入的。在大型陈述中,标准可能隐藏在其他50个表达式中,很容易被遗漏。

可移植性: 您只需从FROM子句中复制一个块,然后将其粘贴到其他位置即可。这给了连接和你需要的任何标准。如果在连接这两个表时总是使用该条件,那么将它放在连接中是最合乎逻辑的。

例如:

FROM
table1 t1
JOIN table2 t2_ABC ON
  t1.c1 = t2_ABC.c1 AND
  t2_ABC.c2 = 'ABC'

如果您需要从表2中获取第二列,您只需将该块复制到记事本中,搜索/重新生成“ABC”,然后将整个新代码块准备好重新粘贴。

其他: 在内部和外部连接之间进行更改也更容易,而不必担心WHERE子句中可能存在的任何标准。

我尽可能严格保留WHERE子句用于运行时条件。

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

答案 3 :(得分:2)

在我通知之前,我想最后说一句话,那之前.. 两种方式都可以提供相同的性能或使用的条件子句可能会在某些答案中找到更快的速度。

但我发现了一个区别,你可以用它来满足你的逻辑需求..

  1. 使用 ON 子句中的条件不会过滤/跳过要选择的行,而是根据条件将连接列设为空

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

答案 4 :(得分:1)

我认为你不会找到适用于所有情况的有限答案。 2并不总是可以互换的 - 因为对于某些查询(一些左连接),您将通过将标准放在WHERE与FROM行中来得出不同的结果。

在您的情况下,您应该评估这两个查询。在SSMS中,您可以查看这两个查询的估计和实际执行计划 - 这将是确定哪个更优化的良好的第一步。你也可以查看时间&amp;每个IO(设置统计时间,设置统计信息) - 这也将为您提供决策信息。

如果您的问题中存在查询 - 我敢打赌他们都会提出相同的查询计划 - 所以在这种情况下它可能并不重要,但在其他情况下它可能产生不同的计划。 / p>

试试这个以查看2 ...

之间的区别
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

答案 5 :(得分:0)

这可能看起来很轻浮,但答案是查询分析器为哪个查询生成最有效的计划。

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

答案 6 :(得分:0)

两者都没有效率,使用WHERE方法被认为是旧方法(http://msdn.microsoft.com/en-us/library/ms190014.aspx)。你可以查看执行计划,看看他们做同样的事情。

答案 7 :(得分:0)

熟悉SQL Management Studio中的估计执行计划!!就像其他人所说的那样,无论你做什么,你都会受到分析仪的支配,所以相信它的估计。我猜你提供的两个会产生完全相同的计划。

如果是改变发展文化的尝试,那就选择能给你更好的计划;对于相同的,遵循文化

我在其他“效率”帖子上评论了这一点(这是真诚和讽刺的) - 如果这是你的瓶颈所在,那么对你和你的团队来说是高五。

答案 8 :(得分:0)

案例1(JOIN中的条件)更适合封装,增加封装通常是一件好事:减少复制/粘贴遗漏到另一个查询,如果以后转换为LEFT JOIN减少错误,并增加可读性(相关的东西在一起)在WHERE子句中减去&#34; noise&#34;在这种情况下,WHERE子句仅捕获跨多个表的主表标准或条件。