2016-09-16 59 views
0

我是SQL新手,我想知道如果我在查詢中同時使用WHERE和HAVING子句,HAVING子句中的條件順序很重要。例如,對於以下查詢(從書中取出),它們是否完全一樣?我的理解是HAVING被應用於GROUP數據,這些數據已經被WHERE子句過濾,然後SUM()函數將只應用於那些過濾的數據。但是,在第二個查詢中,事先未應用WHERE子句,並且在HAVING子句末尾應用條件InvoiceDate BETWEEN'2016-01-01'和'2016-01-31',因此SUM()將從所有數據計算,這與第一個查詢不同。我理解對嗎?在SQL中的having子句中,條件的順序是否重要?

-- First Query 
SELECT 
    InvoiceDate, 
    COUNT(*) AS InvoiceQty, 
    SUM(InvoiceTotal) AS InvoiceSum 
FROM 
    Invoices 
WHERE 
    InvoiceDate BETWEEN '2016-01-01' AND '2016-01-31' 
GROUP BY 
    InvoiceDate 
HAVING 
    COUNT(*) > 1 
     AND SUM(InvoiceTotal) > 100 
ORDER BY 
    InvoiceDate DESC; 

-- Second Query 
SELECT 
    InvoiceDate, 
    COUNT(*) AS InvoiceQty, 
    SUM(InvoiceTotal) AS InvoiceSum 
FROM 
    Invoices 
GROUP BY 
    InvoiceDate 
HAVING 
    COUNT(*) > 1 
     AND SUM(InvoiceTotal) > 100 
     AND InvoiceDate BETWEEN '2016-01-01' AND '2016-01-31' 
ORDER BY 
    InvoiceDate DESC; 

回答

1

訂單在HAVING條款中應該沒有關係。無論如何,大部分工作都是由GROUP BY完成的。如果其中一個子句檢查費用高得多(例如,由於使用用戶定義的函數),則可能有區別。雖然你的查詢沒有這樣的條件。

另一方面,HAVINGWHERE條款中的條件之間的差異很重要。而且,你可以重寫第二查詢爲:

SELECT InvoiceDate, COUNT(*) AS InvoiceQty, 
     SUM(InvoiceTotal) AS InvoiceSum 
FROM Invoices 
WHERE InvoiceDate BETWEEN '2016-01-01' AND '2016-01-31' 
GROUP BY InvoiceDate 
HAVING COUNT(*) > 1 AND SUM(InvoiceTotal) > 100 
ORDER BY InvoiceDate DESC; 

過濾之前GROUP BY通常是更有效,因爲它減少了處理彙集所需的數據量。

1

以下步驟顯示了SQL Server數據庫中SELECT語句的邏輯處理順序或綁定順序。此順序決定了在一個步驟中定義的對象何時可用於後續步驟中的子句。

  1. FROM
  2. ON
  3. JOIN
  4. WHERE
  5. GROUP BY WITH CUBE或WITH ROLLUP
  6. HAVING
  7. SELECT
  8. DISTINCT
  9. ORDER BY
  10. TOP

既然現在你知道了訂單,就可以找出處理將會如何。請參閱this link瞭解更多信息。

0

你假設正確。這兩個查詢有相同的結果,但第一個查詢通常應該是qicker,因爲正如你所說的那樣,它會立即消除不需要的數據,而不是在解除它之前對其進行所有計算。

如果數據庫系統有一個好的查詢優化器,它可能會注意到第二個查詢中的HAVING子句的一部分可以移動到WHERE,並且可能會在內部重新編寫該查詢,因此您最終將查詢# 1在這兩種情況下。但你不應該依賴這一點。儘可能寫出您的查詢,即使用查詢#1。