2010-07-19 22 views
38

supponiamo di avere questa tabellauso mysql SUM() in una clausola WHERE

id | cash 
1 200 
2 301 
3 101 
4 700 

e voglio tornare il prima riga in cui la somma di tutti i contanti precedente è maggiore di un certo valore:

Quindi, per esempio, se voglio restituire la prima riga in cui la somma di tutti i contanti precedenti è maggiore di 500, è necessario tornare alla riga 3

Come faccio a farlo usando l'istruzione mysql?

utilizzando WHERE SUM(cash) > 500 non funziona

+1

Si desidera selezionare 'id = 3' perché' 200 + 300> = 500' o perché '501> 500'? – Dolph

+0

Stai includendo una clausola ORDER BY? Non si può davvero dire di ottenere il record "successivo" perché le righe non sono memorizzate in un ordine particolare. – Robot

+0

è perché 200 + 301> = 500 ... sì ho provato l'ordine e avendo clausole pure ma in questo scenario avrebbero restituito la riga 4 perché la riga 4 è> = 500, non la riga 3 come previsto –

risposta

76

È possibile utilizzare solo aggregati per il confronto nella clausola HAVING:

GROUP BY ... 
    HAVING SUM(cash) > 500 

La clausola HAVING richiede di definire una clausola GROUP BY.

per ottenere la prima riga in cui la somma di tutti i contanti precedente è maggiore di un certo valore, utilizzare:

SELECT y.id, y.cash 
    FROM (SELECT t.id, 
       t.cash, 
       (SELECT SUM(x.cash) 
        FROM TABLE x 
       WHERE x.id <= t.id) AS running_total 
     FROM TABLE t 
    ORDER BY t.id) y 
WHERE y.running_total > 500 
ORDER BY y.id 
    LIMIT 1 

Poiché la funzione di aggregazione avviene in una sottoquery, l'alias colonna per potervi fare riferimento nella clausola WHERE.

+0

penso la sua modifica ha chiarito cosa intendeva e ha reso questo non più vero –

+0

@ Michael Mrozek: Thx per l'heads up, pensa di averlo capito. –

+0

Hi there, grazie per l'aiuto Mi chiedo sulla necessità o meno di questo codice si comporta bene su un grande tavolo però Eventuali commenti sui costi delle prestazioni di utilizzo di questo approccio su un database di grandi dimensioni? –

0

Quando si utilizzano le funzioni di aggregazione per filtrare, è necessario utilizzare un'istruzione HAVING.

SELECT * 
FROM tblMoney 
HAVING Sum(CASH) > 500 
5

Non testato, ma penso che questo sarà vicino?

SELECT m1.id 
FROM mytable m1 
INNER JOIN mytable m2 ON m1.id < m2.id 
GROUP BY m1.id 
HAVING SUM(m1.cash) > 500 
ORDER BY m1.id 
LIMIT 1,2 

L'idea è di riassumere tutte le righe precedenti, ottenere solo quelli in cui la somma delle righe precedenti è> 500, quindi passare uno e restituire il successivo.

+0

Questo non funziona come restituisce 2. Usando 'SELECT m2.id' invece di' SELECT m1.id' restituisce 3 - l'output atteso. Ma cosa succede se i 'id's non sono in ordine. Dovresti usare 'ORDER BY m2.id' invece di' ORDER BY m1.id' la soluzione? Ma la clausola 'ORDER BY' rende l'ordine mentre mostra l'output, giusto? Quindi puoi spiegare come 'id's possa essere ordinato in ordine' ASC' quando la relazione 'JOIN' funziona invece di quando viene presentato il risultato? –

3

In generale, una condizione nella clausola WHERE di una query SQL può fare riferimento solo a una singola riga. Il contesto di una clausola WHERE viene valutato prima che qualsiasi ordine sia stato definito da una clausola ORDER BY e non esiste un ordine implicito in una tabella RDBMS.

È possibile utilizzare una tabella derivata per unire ciascuna riga al gruppo di righe con un valore minore id e produrre la somma di ciascun gruppo di somma. Quindi prova dove la somma soddisfa il tuo criterio.

CREATE TABLE MyTable (id INT PRIMARY KEY, cash INT); 

INSERT INTO MyTable (id, cash) VALUES 
    (1, 200), (2, 301), (3, 101), (4, 700); 

SELECT s.* 
FROM (
    SELECT t.id, SUM(prev.cash) AS cash_sum 
    FROM MyTable t JOIN MyTable prev ON (t.id > prev.id) 
    GROUP BY t.id) AS s 
WHERE s.cash_sum >= 500 
ORDER BY s.id 
LIMIT 1; 

uscita:

+----+----------+ 
| id | cash_sum | 
+----+----------+ 
| 3 |  501 | 
+----+----------+ 
+0

mostra errore: '# 1052 - La colonna' cassa 'nella lista dei campi è ambigua' –

+0

@IstiaqueAhmed, grazie per averlo capito. Ho aggiunto un nome di correlazione quindi è 'SUM (prev.cash)' ora. Questo dovrebbe risolvere l'errore. –

+0

E ora mostra 'id' come 2 invece di 3 e' cash_sum' 501.00. –