Создайте столбец кумулятивной суммы в 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)

UPDATE t
SET cumulative_sum = (
 SELECT SUM(x.count)
 FROM t x
 WHERE x.id <= t.id
)

Образец запроса

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 │
└─────┴──────┴────────────────┘

db скрипка


вы также можете создать триггер, который будет вычислять сумму перед каждой вставить

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 ;