Агрегат SQL-запроса может не отображаться в предложении WHERE - PullRequest
16 голосов
/ 23 августа 2011

У меня есть этот оператор SQL, и SQL Server выдает мне следующую ошибку:

Агрегат может не отображаться в предложении WHERE, если он не входит в подзапрос, содержащийся в предложении HAVING или в 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 не нравятся агрегированные суммы.

Ответы [ 3 ]

26 голосов
/ 23 августа 2011

Используйте 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
2 голосов
/ 23 августа 2011

Используйте «Имея» для использования с агрегатными функциями.

Вот ссылка: http://msdn.microsoft.com/en-us/library/ms180199.aspx

0 голосов
/ 23 августа 2011

В предложении where я хочу получать только те записи, где самые старые Дата неоплаченного счета-фактуры больше, чем DelinquentDaysThreshhold (в днях)

Некоторые соображения производительности с предложением HAVING:

Когда вы используете GROUP BY с предложением HAVING, GROUP BY Предложение разделяет строки на наборы сгруппированных строк и объединяет их значения, а затем предложение HAVING устраняет нежелательные агрегированные групп. Во многих случаях вы можете написать свое предложение select, чтобы оно содержать только предложения WHERE и GROUP BY без предложения HAVING.

В качестве альтернативы предложению 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...