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?
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 :)
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
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:
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
.r
, est requis par MySQL pour toute vue de sous-requête/table dérivée/inlineMises en garde:
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)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 │
└─────┴──────┴────────────────┘
UPDATE t
SET cumulative_sum = (
SELECT SUM(x.count)
FROM t x
WHERE x.id <= t.id
)
select Id, Count, @total := @total + Count as cumulative_sum
from YourTable, (Select @total := 0) as total ;
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
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
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.