SELECT
DAYOFYEAR(O.`date`) AS d,
COUNT(*),
(select count(*) from `orders`
where DAYOFYEAR(`date`) <= d and `hasPaid` > 0)
FROM
`orders` as O
WHERE
O.`hasPaid` > 0
GROUP BY d
ORDER BY d
Это потребует некоторой синтаксической настройки (у меня нет MySQL для тестирования), но это показывает вам идею. Подзапрос должен просто вернуться назад и сложить все свежее, что вы уже включили во внешний запрос, и он должен делать это для каждой строки.
Посмотрите на этот вопрос о том, как использовать объединения для достижения того же.
Для решения проблем, связанных с ухудшением производительности с ростом данных: так как есть макс. 366 дней в году, и я предполагаю, что вы не выполняете этот запрос для нескольких лет, подзапрос будет оцениваться до 366 раз. С правильными индексами даты и флагом hasPaid все будет в порядке.