31

我有一个相对简单的查询连接两个表。“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 < 某个固定日期,那么实际上连接两个表的任何标准都不会改变答案。

4

9 回答 9

28

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

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

只是保持物品清洁并将物品放在它们所属的地方,IMO。

显然,在某些使用 LEFT OUTER JOIN 的情况下,标准的放置确实会对返回的结果产生影响——当然,这些情况将被排除在我的建议之外。

马克

于 2009-09-09T20:30:54.447 回答
3

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

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

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

于 2009-09-09T20:36:43.953 回答
3

我更喜欢在连接中有任何硬编码标准。它使 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。

于 2013-06-06T02:08:35.430 回答
3

在此之前,我最后要说的一件事是我通知的。这两种方式都可能提供相同的性能,或者使用Where子句中的标准可能会比某些答案中的要快一些。

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

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

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

于 2017-03-02T09:52:51.583 回答
1

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

在您的情况下,您应该评估这两个查询。在 SSMS 中,您可以查看这两个查询的估计和实际执行计划——这将是确定哪个更优化的良好第一步。您还可以查看每个时间和 IO(设置统计时间,设置统计 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
于 2009-09-09T20:33:49.387 回答
0

这似乎轻率,但答案是查询分析器为其生成最有效计划的任何查询。

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

于 2009-09-09T20:30:12.577 回答
0

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

于 2009-09-09T20:31:09.257 回答
0

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

如果这是一种改变开发文化的尝试,请选择能够为您提供更好计划的文化;对于相同的,遵循文化

我已经在类似这篇文章的其他“效率”帖子上评论过这个(它既真诚又讽刺)——如果这是你的瓶颈所在,那么对你和你的团队高五。

于 2009-09-09T20:46:48.270 回答
0

案例 1(JOIN 中的标准)更适合封装,增加封装通常是一件好事:减少对另一个查询的复制/粘贴遗漏,如果稍后转换为 LEFT JOIN,则减少错误,并提高可读性(相关内容一起减少”噪音”在 WHERE 子句中)。在这种情况下,WHERE 子句仅捕获主体表条件或跨越多个表的条件。

于 2017-04-13T13:54:42.320 回答