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

42
demandé sur Dolph 2010-07-19 23:40:24

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.

85
répondu OMG Ponies 2010-07-19 19:47:57

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.

5
répondu Eric Petroelje 2010-07-19 19:51:46

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 |
+----+----------+
3
répondu Bill Karwin 2017-10-25 16:08:15

Lorsque vous utilisez des fonctions d'agrégation pour filtrer, vous devez utiliser une instruction HAVING.

SELECT *
FROM tblMoney
HAVING Sum(CASH) > 500
0
répondu Robot 2010-07-19 19:42:50