SQL查询聚合可能不会出现在WHERE子句中

时间:2011-08-23 19:41:50

标签: sql sql-server sql-server-2005

我有这个SQL语句,SQL Server给了我以下错误:

  

聚合可能不会出现在WHERE子句中,除非它在a中   包含在HAVING子句或选择列表中的子查询。

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不喜欢汇总金额。

3 个答案:

答案 0 :(得分:26)

使用错误消息提示的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

答案 1 :(得分:2)

使用“Having”用于聚合函数。

下面是一个链接:http://msdn.microsoft.com/en-us/library/ms180199.aspx

答案 2 :(得分:0)

  

在where子句中,我只想拉最旧的记录   未付的结算发票日期大于   DelinquentDaysThreshhold(以天为单位)

HAVING子句的一些性能考虑因素:

  

将GROUP BY与HAVING子句一起使用时,GROUP BY   子句将行划分为多组分组行并聚合它们   值,然后HAVING子句消除了不需要的聚合   组。在许多情况下,您可以编写您的select语句   仅包含没有HAVING子句的WHERE和GROUP BY子句。

作为HAVING子句的替代方法,您还可以使用派生表来解决此问题:

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