2011-08-23 5 views
13

tengo esta sentencia SQL y SQL Server me está dando el siguiente error:agregada de consultas SQL puede no aparecer en la cláusula 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 

en la cláusula WHERE, sólo quiero tirar de registros en los que las la fecha más antigua de la Factura de facturación no pagada es mayor que la Hora de entrega diferida (en días), O la Importe de la suma en adelanto (un valor calculado) es mayor que el Umbral de acumulación del importe.
Por alguna razón, SQL Server no le gusta los montos agregados.

+1

Recuerde leer las preguntas más frecuentes acerca de la reputación y la votación etc http://meta.stackexchange.com/questions/7237/how-does-reputation-work – gbn

+0

Es no sólo SQL-servidor que no permite utilizando agregados en la cláusula 'WHERE', esto es una cosa SQL general, es por eso que se introdujo' HAVING'. – Johan

Respuesta

25

Utilice el teniendo como por el mensaje de error, lo que requiere 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 
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)

Algunas consideraciones de rendimiento con la cláusula 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.

Como alternativa a la cláusula HAVING, también puede usar tablas derivadas para s Olve este problema:

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

¿Dónde copió/pegó esta respuesta genérica que no coincide con la pregunta de OP? – gbn

+1

@gbn: ¿Disculpe? El OP preguntó cómo usar un total agregado en la cláusula where. Esto logra eso. No es necesario ser grosero, amigo. –

+2

Usted usaría HAVING entonces, no una tabla derivada. Voy a reformular entonces: ¿por qué gastaste tiempo escribiendo este fragmento en lugar de usar la consulta original de OP? – gbn

Cuestiones relacionadas