Как рассчитать обратную текущую сумму в MySQL - PullRequest
2 голосов
/ 29 мая 2020

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

SELECT t1.date, t1.ant, t1.hab,  
(@csum:= @csum + t1.hab) as cumulative_hab
from(
SELECT date,
        ant, 
        sum(num_habit) as hab
        from xxxxxxxxxx
        WHERE date BETWEEN CURDATE() - INTERVAL 5 DAY AND CURDATE()
        group by ant) AS t1
,(select @csum := 0) vars
order by t1.ant

Моя таблица выглядит так

date       ant   hab    cumulative_hab
24-05-2020  0   382,000   382,000
24-05-2020  1   28,000    410,000
24-05-2020  2   26,000    436,000
24-05-2020  3   11,000    447,000
24-05-2020  4   29,000    476,000
24-05-2020  6   6,000     482,000
24-05-2020  7   12,000    494,000
28-05-2020  8   50,000    544,000
24-05-2020  12  5,000     549,000
24-05-2020  13  6,000     555,000

Мне нужен еще один столбец с обратной текущей суммой (обратная кумулятивная сумма) , вычисляется первое значение 555 - 382

 date      ant   hab    cumulative_hab   reverse_cum_hab
24-05-2020  0   382,000   382,000             555,000
24-05-2020  1   28,000    410,000             173,000, 
24-05-2020  2   26,000    436,000             145,000
24-05-2020  3   11,000    447,000             119,000
24-05-2020  4   29,000    476,000             108,000
24-05-2020  6   6,000     482,000              79,000
24-05-2020  7   12,000    494,000              73,000
28-05-2020  8   50,000    544,000              61,000
24-05-2020  12  5,000     549,000              11,000
24-05-2020  13  6,000     555,000               6,000

1 Ответ

2 голосов
/ 29 мая 2020

Для начала: если вы используете MySQL 8.0, вы можете легко сделать это с помощью оконных функций:

select 
    date,
    ant,
    sum(num_habit) as hab,
    sum(sum(num_habit)) over(order by date) cumulative_hab,
    sum(sum(num_habit)) over(order by date desc) reverse_cumulative_hab
from mytable
where date between current_date - interval 5 day and current_date
group by date, ant
order by date

В более ранних версиях это сложнее. Я бы предложил объединить два запроса:

select t.*, r.reverse_cumulative_hab
from (
    select t.*, @csum := @csum + hab cumulative_hab
    from (
        select date, ant, sum(num_habit) as hab
        from mytable
        where date between current_date - interval 5 day and current_date
        group by date, ant
        order by date
    ) t
    cross join (select @csum := 0) x
) t
inner join (
    select t.*, @rcsum := @rcsum + hab reverse_cumulative_hab
    from (
        select date, ant, sum(num_habit) as hab
        from mytable
        where date between current_date - interval 5 day and current_date
        group by date, ant
        order by date desc
    ) t
    cross join (select @rcsum := 0) x
) r on r.date = t.date
order by t.date

Это предполагает отсутствие дубликатов ant на date.

Также возможно упростить logi c и вычислить обратное sum, взяв разницу между кумулятивной суммой и общей суммой:

select t.*, z.total_hab - t.cumulative_hab reverse_cumulative_hab
from (
    select t.*, @csum := @csum + hab cumulative_hab
    from (
        select date, ant, sum(num_habit) as hab
        from mytable
        where date between current_date - interval 5 day and current_date
        group by date, ant
        order by date
    ) t
    cross join (select @csum := 0) x
) t
cross join (
    select sum(num_habit) as total_hab
    from mytable
    where date between current_date - interval 5 day and current_date
) z
order by date

Обратите внимание, что эти запросы безопаснее, чем ваш исходный код в отношении порядка строк: записи упорядочиваются в подзапросе перед вычисляется совокупная сумма.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...