Промежуточный итог с каждой группой, использующей MySQL

0

Я пытаюсь написать SQL, чтобы вычислить общее количество в каждой группе в следующем входе. Просто интересно, как я могу это сделать с помощью MySQL. Я знаю, как это сделать в обычном SQL, используя аналитические функции, но не в MySQL. Не могли бы вы поделиться своими мыслями о том, как его реализовать.

SQL Fiddle: http://sqlfiddle.com/#!9/59366d/19

SQL с использованием оконной функции:

SELECT e.Id,
       SUM( e.Salary ) OVER( PARTITION BY e.Id ORDER BY e.Month  ) AS cumm_sal
  FROM Employee e 
LEFT JOIN
       (
          SELECT Id,MAX(Month) AS maxmonth
            FROM Employee
          GROUP BY Id
        ) emax
    ON e.Id = emax.Id
WHERE e.Month != emax.maxmonth
ORDER BY e.Id,e.Month DESC;    

Вход:

Create table Employee (Id int, Month int, Salary int);

insert into Employee (Id, Month, Salary) values ('1', '1', '20');
insert into Employee (Id, Month, Salary) values ('2', '1', '20');
insert into Employee (Id, Month, Salary) values ('1', '2', '30');
insert into Employee (Id, Month, Salary) values ('2', '2', '30');
insert into Employee (Id, Month, Salary) values ('3', '2', '40');
insert into Employee (Id, Month, Salary) values ('1', '3', '40');
insert into Employee (Id, Month, Salary) values ('3', '3', '60');
insert into Employee (Id, Month, Salary) values ('1', '4', '60');
insert into Employee (Id, Month, Salary) values ('3', '4', '70');

Выход:

| Id | Month | Salary |
|----|-------|--------|
| 1  | 3     | 90     |
| 1  | 2     | 50     |
| 1  | 1     | 20     |
| 2  | 1     | 20     |
| 3  | 3     | 100    |
| 3  | 2     | 40     |
  • 0
    Как насчет использования оконных функций в MySQL? dev.mysql.com/doc/refman/8.0/en/window-functions-usage.html
  • 0
    Речь идет о решении без использования оконных функций.
Показать ещё 1 комментарий
Теги:
running-total

1 ответ

3
Лучший ответ

В MySQL наиболее эффективным является использование переменных:

select e.*,
       (@s := if(@id = e.id, @s + salary,
                 if(@id := e.id, salary, salary)
                )
       ) as running_salary
from (select e.*
      from employee e
      order by e.id, e.month
     ) e cross join
     (select @id := -1, @s := 0) params;

Вы также можете сделать это с помощью коррелированного подзапроса:

select e.*,
       (select sum(e2.salary)
        from employee e2
        where e2.id = e.id and e2.month <= e.month
       ) as running_salary
from employee e;
  • 0
    Обратите внимание, что использование переменных (первое решение) будет работать только в MySQL (насколько я знаю), поэтому это не стандартное решение, которое может работать на других базах данных. С другой стороны, коррелированный подзапрос (второе решение) является стандартным решением; однако коррелированные подзапросы медленны по своей природе и будут становиться медленнее, чем больше у вас строк. Но я думаю, это характер вашей проблемы, и это может быть лучшим решением.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню