Вы получаете несколько сложных ответов. Я думаю, что это проще. Начните с знания, что мы можем легко суммировать за каждый месяц:
SELECT SUM(amount) as monthtotal,
type,
MONTH(date) as month,
YEAR(date) as year
FROM A LEFT JOIN B on A.B_id=B.id
GROUP BY type,month,year
Исходя из этих данных, мы можем использовать переменную для получения промежуточного итога. Лучше всего делать, инициализируя переменную, но не обязательно. Мы можем получить необходимые данные, например:
SET @running := 0;
SELECT (@running := @running + monthtotal) as running, type, LAST_DAY(CONCAT(year,'-',month,'-',1))
FROM
(SELECT SUM(amount) as monthtotal,type,MONTH(date) as month,YEAR(date) as year FROM A LEFT JOIN B on A.B_id=B.id GROUP BY type,month,year) AS totals
ORDER BY year,month
. Вам действительно нужен соединитель, который поддерживает несколько операторов, или несколько вызовов для инициализации переменной. Несмотря на то, что вы можете проверить переменную null и установить значение по умолчанию 0, у вас все еще есть проблема, если вы выполняете запрос второй раз.
Последнее, если вы действительно хотите, чтобы типы суммировались отдельно:
SET @running5 := 0;
SET @running7 := 0;
SELECT
LAST_DAY(CONCAT(year,'-',month,'-',1)),
(@running5 := @running5 + (CASE WHEN type=5 THEN monthtotal ELSE 0 END)) as running5,
(@running7 := @running7 + (CASE WHEN type=7 THEN monthtotal ELSE 0 END)) as running7
FROM
(SELECT SUM(amount) as monthtotal,type,MONTH(date) as month,YEAR(date) as year FROM A LEFT JOIN B on A.B_id=B.id GROUP BY type,month,year) AS totals
ORDER BY year,month
Мы все еще не показываем месяцы, когда нет данных. Я не уверен, что это требование. Но для этого нужен только один проход таблицы A.
Кроме того, убедитесь, что идентификатор таблицы B. проиндексирован.