2011-08-23 869 views
13

我有這樣的SQL語句和SQL Server是給我下面的錯誤:SQL查詢聚合不應出現在WHERE子句

An aggregate may not appear in the WHERE clause unless it is in a subquery contained in a HAVING clause or a select list.

SELECT 
    SUM(M1.InvoiceTotal)-SUM(M1.AmountApplied) as PastDueAmount 
    , M1.BillingID 
    , M2.Name 
    , M2.DelinquentDaysThreshold 
    , M2.DelinquentAmountThreshold 
    , DATEDIFF(d, MIN(BillingDate),GETDATE()) as DaysLate 
FROM Invoices M1 
LEFT JOIN ClientAccounts M2 ON M1.BillingID = M2.ID 
WHERE 
    InvoiceTotal <> AmountApplied 
    AND M2.DelinquentDaysThreshold > DATEDIFF(d, MIN(BillingDate),GETDATE()) 
    OR (SUM(M1.InvoiceTotal)-SUM(M1.AmountApplied)) > M2.DelinquentAmountThreshold 
GROUP BY 
    M1.BillingID 
    , M2.Name 
    , M2.DelinquentDaysThreshold 
    , M2.DelinquentAmountThreshold 

在where子句中,我只是想拉記錄中,其中最早的未付帳單發票日期大於DelinquentDaysThreshhold(天),或者PastDueAmount(計算的值)大於DelinquentAmountThreshold。
由於某些原因,SQL Server不喜歡彙總金額。

+1

請務必閱讀有關的信譽和投票等方面的常見問題http://meta.stackexchange.com/questions/7237/how-does-reputation-work – gbn

+0

這不僅是SQL的服務器不允許使用'WHERE'子句中的聚合,這是一個通用的SQL事物,這就是爲什麼引入'HAVING'的原因。 – Johan

回答

25

使用having按照錯誤信息,這需要一個GROUP BY

SELECT 
    SUM(M1.InvoiceTotal)-SUM(M1.AmountApplied) as PastDueAmount, 
    M1.BillingID, M2.Name, 
    M2.DelinquentDaysThreshold, M2.DelinquentAmountThreshold, 
    DATEDIFF(d, MIN(BillingDate),GETDATE()) as DaysLate 
FROM 
    Invoices M1 
    LEFT JOIN 
    ClientAccounts M2 ON M1.BillingID = M2.ID 
WHERE 
    InvoiceTotal <> AmountApplied 
    AND 
    M2.DelinquentDaysThreshold > DATEDIFF(d, MIN(BillingDate),GETDATE()) 
GROUP BY 
    M1.BillingID, M2.Name, 
    M2.DelinquentDaysThreshold, M2.DelinquentAmountThreshold, 
    DATEDIFF(d, MIN(BillingDate),GETDATE()) 
HAVING 
    (SUM(M1.InvoiceTotal)-SUM(M1.AmountApplied)) > M2.DelinquentAmountThreshold 
0

In the where clause, I only want to pull records where the oldest unpaid Billing Invoice Date is greater than the DelinquentDaysThreshhold (in days)

與HAVING子句的一些性能方面的考慮:

When you use GROUP BY with the HAVING clause, the GROUP BY clause divides the rows into sets of grouped rows and aggregates their values, andthen the HAVING clause eliminates undesired aggregated groups. In many cases,you can write your select statement so it will contain only WHERE and GROUP BY clauses without a HAVING clause.

作爲HAVING子句的替代方法,您還可以使用派生表olve這個問題:

SELECT t1.SomeID, t1.SomeThreshold, totals.NumericTotal 
FROM Table1 t1 
     INNER JOIN (
      SELECT SomeID, SUM(SomeNumericValue) NumericTotal 
      FROM Table1 
      Group By SomeID 
     ) totals 
      ON t1.SomeID = totals.SomeID 
WHERE totals.NumericTotal > t1.SomeThreshold 
+2

你在哪裏複製/粘貼了與OP問題不匹配的通用答案? – gbn

+1

@gbn:不好意思? OP詢問如何在where子句中使用加總。這完成了。不需要粗魯,老兄。 –

+2

然後你會使用HAVING,而不是派生表。然後,我將重新說明:爲什麼你花時間寫這段代碼,而不是使用OP的原始查詢? – gbn