utilisez mysql SUM() dans une clause WHERE
Supposons que j'ai cette table
id | cash
1 200
2 301
3 101
4 700
Et je veux retourner la première ligne dans laquelle la somme de tout l'argent précédent est supérieure à une certaine valeur:
Ainsi, par exemple, si je veux retourner la première ligne dans laquelle la somme de toutes les espèces précédentes est supérieure à 500, is devrait retourner à la ligne 3
Comment puis-je faire cela en utilisant l'instruction mysql?
En utilisant WHERE SUM(cash) > 500
ne fonctionne pas
4 réponses
Vous ne pouvez utiliser des agrégats que pour la comparaison dans la clause HAVING:
GROUP BY ...
HAVING SUM(cash) > 500
La clause HAVING
vous oblige à définir une clause GROUP BY.
Pour obtenir la première ligne où la somme de toutes les espèces précédentes est supérieure à une certaine valeur, utilisez:
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
Étant donné que la fonction d'agrégat se produit dans une sous-requête, l'alias de colonne pour elle peut être référencé dans la clause WHERE.
Pas testé, mais je pense que ce sera proche?
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'idée est la SOMME de toutes les lignes précédentes, obtenir uniquement ceux où la somme des lignes précédentes est > 500, puis sauter et revenir à la prochaine.
En général, une condition de la clause WHERE
d'une requête SQL ne peut référencer qu'une seule ligne. Le contexte d'une clause WHERE
est évalué avant que n'importe quel ordre ait été défini par une clause ORDER BY
, et il n'y a pas d'ordre implicite à une table SGBDR.
Vous pouvez utiliser une table dérivée pour joindre chaque ligne au groupe de lignes avec une valeur id
inférieure et produire la somme de chaque groupe de somme. Ensuite, testez où la somme répond à votre critère.
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;
Sortie:
+----+----------+
| id | cash_sum |
+----+----------+
| 3 | 501 |
+----+----------+
Lorsque vous utilisez des fonctions d'agrégation pour filtrer, vous devez utiliser une instruction HAVING.
SELECT *
FROM tblMoney
HAVING Sum(CASH) > 500