2009-09-09 71 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子句只捕獲跨越多個表的主表標準或標準。