Para atender aos meses ausentes, crie uma tabela de modelo para unir.
Pense nisso como cache. Em vez de percorrer e preencher lacunas, basta ter um calendário armazenado em cache em seu banco de dados.
Você pode até combinar vários calendários (início do mês, início da semana, feriados, dia útil etc.) em uma tabela, com vários sinalizadores e índices de pesquisa.
Você acaba com algo como...
SELECT
calendar.date,
SUM(data.amt)
FROM
calendar
LEFT JOIN
data
ON data.date >= calendar.date
AND data.date < calendar.date + INTERVAL 1 MONTH
WHERE
calendar.date >= '20110101'
AND calendar.date < '20120101'
GROUP BY
calendar.date
EDITAR
Acabei de notar que o OP quer um total em execução.
Isso -é- possível no SQL, mas é extremamente ineficiente. A razão é que o resultado de um mês não é usado para calcular o mês seguinte. Em vez disso, todo o total de execução deve ser calculado novamente.
Por esse motivo, normalmente é altamente recomendável que você calcule o total mensal conforme acima e, em seguida, use seu aplicativo para iterar e fazer os valores totais em execução.
Se você realmente deve fazer isso em SQL, seria algo como ...
SELECT
calendar.date,
SUM(data.amt)
FROM
calendar
LEFT JOIN
data
ON data.date >= @yourFirstDate
AND data.date < calendar.date + INTERVAL 1 MONTH
WHERE
calendar.date >= @yourFirstDate
AND calendar.date < @yourLastDate
GROUP BY
calendar.date