2009-09-09 72 views
21

我有一个相对简单的查询连接两个表。 “Where”标准可以在连接标准中或作为where子句表达。我想知道哪个更有效率。SQL在连接条件或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 <某个固定的日期,所以它实际上没有任何加入两个表的标准确实会改变答案。

+0

实际测试这些查询所花费的时间有什么问题? – ChristopheD 2009-09-09 20:30:00

+2

因为查询的get缓存,但感谢,真的 – Gratzy 2009-09-09 20:35:29

+1

@Gratzy - DBCC FREEPROCCACHE http://msdn.microsoft.com/en-us/library/ms174283.aspx – 2009-09-09 20:48:38

回答

20

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

我总是使用案例#2 - 为什么?因为在我看来,你只应该把建立这两个表之间的JOIN的实际标准放到JOIN子句中 - 其他的东西都属于WHERE子句。

只需保持事物清洁并将物品放在他们所属的地方即IMO。

很明显,有些情况下会出现左外连接,这些标准的位置确实会影响返回的结果 - 当然,这些情况会从我的建议中排除。

马克

+1

+1 - 很好的答案马克 – 2009-09-09 20:39:11

+0

IMO有人会说这种情况下,#1是封装好(在这种情况下,WHERE子句仅用于主表的标准)。 – 2017-04-13 13:37:06

0

它可能看起来很不自然,但答案是查询分析器生成最有效计划的任何查询。

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

0

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

+0

我的例子不是最好的改变连接的第二部分和或where子句是一个固定的日期,而不是销售员表中的日期。 – Gratzy 2009-09-09 20:37:23

+0

啊,好吧,无论哪种情况,执行计划都是你的朋友。分析它以找出哪一个具有最佳性能。我敢打赌,他们会是相同的。 – 2009-09-09 20:42:36

1

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

就你而言,你应该评估这两个查询。在SSMS中,您可以查看这两个查询的估计和实际执行计划 - 这将是确定哪个更优化的第一步。您也可以查看每个时间的& IO(设置统计时间,设置统计数据) - 这也将为您提供信息以作出决定。

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

试试这个,看看之间的差异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 
+0

这将是特别内连接 – Gratzy 2009-09-09 20:43:29

+1

Gratzy - 在这种情况下,我同意marc_s - 过滤条件应保持在查询的WHERE部分,和连接标准应保持在查询的FROM部分。 – 2009-09-09 20:44:38

+0

尽管where标准表具有许多更多的行,但它是否重要?我知道这可能听起来微不足道,但我想知道是否将它作为连接条件的一部分而不是条款 – Gratzy 2009-09-09 20:54:38

0

成为熟悉SQL Management Studio中估计的执行计划!像其他人所说的那样,无论你如何信任它的估计值,你都会受到分析仪的控制。我猜想你提供的两个会产生完全相同的计划。

如果是试图改变发展文化,选择一个给你更好的计划;对于那些相同的人,请遵循文化

我已经评论过其他“效率”这样的帖子(这是真诚的和讽刺的) - 如果这是你的瓶颈所在,那么高五到你和你的团队。

+1

是的,我熟悉预计执行计划。但它不会告诉我为什么它会按照它的方式生成执行计划。我一直在寻找理解为什么一个人可能比另一个更有效率。 – Gratzy 2009-09-09 20:53:06

+0

@Gratzy:http://www.amazon.com/Gurus-Guide-Server-Architecture-Internals/dp/0201700476 – 2009-09-09 21:06:05

3

我更喜欢在连接中有任何硬编码标准。它使得SQL更具可读性和便携性。

可读性: 您可以准确了解要获取的数据,因为所有表格条件都写在连接中。在大型报表中,标准可能被埋在其他50个表达式中,很容易被忽略。

可移植性: 您可以从FROM子句中复制块并将其粘贴到其他位置。这给出了你需要的连接和任何标准。如果您在加入这两个表时始终使用该条件,那么将它放入连接是最合理的。

例如:

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

如果你需要获得一个第二列从表2中你只是复制块到记事本中,搜索/ repalce“ABC”和急和代码准备整个新块粘贴回来。

附加: 在内部和外部连接之间切换也更容易,无需担心可能在WHERE子句中浮动的任何条件。

如果可能,我严格保留WHERE子句用于运行时标准。

至于效率: 如果你指的是执行速度,那么正如其他人所说的那样,这是多余的。 如果你指的是更容易调试和重用的话,我宁愿选择1

+0

总之,在连接标准是封装好,并增加封装通常是更好的。 – 2017-04-13 13:40:01

1

有一两件事我想最后说,我接到通知,在此之前,.. 两种方式都可以给予同样的性能或使用的标准,因此其中子句可能会稍微快一些,如发现在一些答案..

但我确定一个区别,你可以使用你的逻辑需求..

  1. 使用的标准,因此ON子句不会过滤/跳过行选择,而不是连接列将是空基于所述条件

  2. 使用标准中的子句可以过滤/在整个结果跳过行

0

案例1(在连接标准)是封装好,并增加封装通常是一件好事:减少的拷贝/粘贴遗漏到另一个查询,减少错误如果以后转换为左连接,并增加了可读性(相关的东西一起而WHERE子句中的“噪音”更少)。在这种情况下,WHERE子句只捕获跨越多个表的主表标准或标准。