18 votes

L'agrégat de la requête SQL ne peut pas apparaître dans la clause WHERE

J'ai cette instruction SQL et le serveur SQL me donne l'erreur suivante :

Un agrégat peut ne pas apparaître dans la liste WHERE sous-requête contenue dans une clause HAVING ou une liste de sélection.

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

Dans la clause where, je ne veux extraire que les enregistrements dont la date de la plus ancienne facture impayée est supérieure au seuil DelinquentDaysThreshhold (en jours), OU dont le PastDueAmount (une valeur calculée) est supérieur au seuil DelinquentAmountThreshold (en jours).
Pour une raison quelconque, SQL Server n'aime pas les montants agrégés.

34voto

gbn Points 197263

Utiliser le HAVING comme l'indique le message d'erreur, qui nécessite un 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

2voto

Matthew Points 10499

Utiliser "Avoir" pour les fonctions agrégées.

Voici un lien : http://msdn.microsoft.com/en-us/library/ms180199.aspx

0voto

James Johnson Points 29414

Dans la clause where, je ne veux extraire que les enregistrements où l'ol date de facturation impayée la plus ancienne est supérieure à la valeur seuil de DelinquentDaysThreshhold (en jours)

Quelques considérations sur les performances de la clause HAVING :

W divise les lignes en ensembles de lignes groupées et agrège leurs valeurs. valeurs, puis la clause HAVING élimine les groupes agrégés indésirables. indésirables. Dans de nombreux cas, vous pouvez écrire votre instruction select de manière à ce qu'elle ne contienne que les clauses WHERE et GROUP BY. qu'elle ne contienne que les clauses WHERE et GROUP BY sans clause HAVING.

Comme alternative à la clause HAVING, vous pouvez également utiliser des tables dérivées pour résoudre ce problème :

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X