web-dev-qa-db-fra.com

Créer une colonne de somme cumulée dans MySQL

J'ai une table qui ressemble à ceci:

id   count
1    100
2    50
3    10

Je veux ajouter une nouvelle colonne appelée cumulative_sum, afin que la table ressemble à ceci:

id   count  cumulative_sum
1    100    100
2    50     150
3    10     160

Existe-t-il une instruction de mise à jour MySQL permettant de le faire facilement? Quel est le meilleur moyen d'y parvenir?

69
Kirk Ouimet

Si les performances sont un problème, vous pouvez utiliser une variable MySQL:

set @csum := 0;
update YourTable
set cumulative_sum = (@csum := @csum + count)
order by id;

Sinon, vous pouvez supprimer le cumulative_sum colonne et calculez-la sur chaque requête:

set @csum := 0;
select id, count, (@csum := @csum + count) as cumulative_sum
from YourTable
order by id;

Ceci calcule la somme courante de manière courante :)

84
Andomar

En utilisant une requête corrélée:


  SELECT t.id,
         t.count,
         (SELECT SUM(x.count)
            FROM TABLE x
           WHERE x.id <= t.id) AS cumulative_sum
    FROM TABLE t
ORDER BY t.id

Utilisation de variables MySQL:


  SELECT t.id,
         t.count,
         @running_total := @running_total + t.count AS cumulative_sum
    FROM TABLE t
    JOIN (SELECT @running_total := 0) r
ORDER BY t.id

Remarque:

  • La JOIN (SELECT @running_total := 0) r est une jointure croisée et permet la déclaration de variable sans nécessiter une commande séparée SET.
  • L'alias de table, r, est requis par MySQL pour toute vue de sous-requête/table dérivée/inline

Mises en garde:

  • MySQL spécifique; non portable vers d'autres bases de données
  • Le ORDER BY Est important; il garantit que l'ordre correspond au PO et peut avoir des implications plus importantes pour une utilisation de variables plus complexe (IE: fonctionnalité psuedo ROW_NUMBER/RANK, qui manque à MySQL)
98
OMG Ponies

MySQL 8.0/MariaDB prend en charge l’interface SUM(col) OVER() :

SELECT *, SUM(cnt) OVER(ORDER BY id) AS cumulative_sum
FROM tab;

Sortie:

┌─────┬──────┬────────────────┐
│ id  │ cnt  │ cumulative_sum │
├─────┼──────┼────────────────┤
│  1  │ 100  │            100 │
│  2  │  50  │            150 │
│  3  │  10  │            160 │
└─────┴──────┴────────────────┘

db <> violon

8
Lukasz Szozda
UPDATE t
SET cumulative_sum = (
 SELECT SUM(x.count)
 FROM t x
 WHERE x.id <= t.id
)
3
Dercsár
select Id, Count, @total := @total + Count as cumulative_sum
from YourTable, (Select @total := 0) as total ;
3
Ashutosh SIngh

Exemple de requête

SET @runtot:=0;
SELECT
   q1.d,
   q1.c,
   (@runtot := @runtot + q1.c) AS rt
FROM
   (SELECT
       DAYOFYEAR(date) AS d,
       COUNT(*) AS c
    FROM  orders
    WHERE  hasPaid > 0
    GROUP  BY d
    ORDER  BY d) AS q1
2
Jazz

Vous pouvez également créer un déclencheur qui calculera la somme avant chaque insertion.

delimiter |

CREATE TRIGGER calCumluativeSum  BEFORE INSERT ON someTable
  FOR EACH ROW BEGIN

  SET cumulative_sum = (
     SELECT SUM(x.count)
        FROM someTable x
        WHERE x.id <= NEW.id
    )

    set  NEW.cumulative_sum = cumulative_sum;
  END;
|

Je n'ai pas testé cela

1
Greg

sélectionnez id, count, sum (count) sur (order by count desc) en tant que cumulative_um à partir de tableName;

J'ai utilisé la fonction d'agrégation sum sur la colonne count, puis la clause over. Il résume chaque ligne individuellement. La première rangée sera juste à 100. La deuxième rangée sera à 100 + 50. La troisième rangée est 100 + 50 + 10 et ainsi de suite. Donc, fondamentalement, chaque ligne est la somme de toutes les lignes précédentes et la dernière, la somme de toutes les lignes. Donc, la façon de regarder cela est que chaque ligne est la somme du montant où l'ID est inférieur ou égal à lui-même.

0
Pavan Bashetty