Создайте столбец кумулятивной суммы в MySQL
у меня есть таблица, которая выглядит так:
id   count
1    100
2    50
3    10
Я хочу добавить новый столбец cumulative_sum, чтобы таблица выглядела так:
id   count  cumulative_sum
1    100    100
2    50     150
3    10     160
есть ли оператор обновления MySQL, который может сделать это легко? Как лучше всего этого добиться?
7 ответов
Если производительность является проблемой, вы можете использовать переменную в MySQL:
set @csum := 0;
update YourTable
set cumulative_sum = (@csum := @csum + count)
order by id;
кроме того, вы можете удалить cumulative_sum столбец и вычислить его по каждому запросу:
set @csum := 0;
select id, count, (@csum := @csum + count) as cumulative_sum
from YourTable
order by id;
это вычисляет текущую сумму в пути :)
использование коррелированного запроса:
  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
использование переменных 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
Примечание:
- на JOIN (SELECT @running_total := 0) rявляется перекрестным соединением и позволяет объявлять переменные, не требуя отдельного .
- псевдоним таблицы, r, требуется MySQL для любого подзапроса / производной таблицы / встроенного представления
предостережения:
- MySQL specific; не переносится на другие базы данных
- на ORDER BYважно; это гарантирует, что порядок соответствует OP и может иметь большие последствия для более сложного использования переменных (т. е.: функциональность psuedo ROW_NUMBER/RANK, которой не хватает MySQL)
Образец запроса
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
MySQL 8.0 / MariaDB поддерживает оконные SUM(col) OVER():
SELECT *, SUM(cnt) OVER(ORDER BY id) AS cumulative_sum
FROM tab;
выход:
┌─────┬──────┬────────────────┐
│ id  │ cnt  │ cumulative_sum │
├─────┼──────┼────────────────┤
│  1  │ 100  │            100 │
│  2  │  50  │            150 │
│  3  │  10  │            160 │
└─────┴──────┴────────────────┘
вы также можете создать триггер, который будет вычислять сумму перед каждой вставить
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;
|
Я не тестировал это
select Id, Count, @total := @total + Count as cumulative_sum
from YourTable, (Select @total := 0) as total ;
