Dergelijke problemen zijn gemakkelijker op te lossen als je een kalendertabel hebt met alle datums die je nodig hebt. Als je zo'n tabel niet hebt, kun je deze maken met een query als deze:
create table `calendar` (
`date` DATE NOT NULL,
PRIMARY KEY (`date`)
)
select DATE_ADD('1900-01-01',INTERVAL t4.c*10000 + t3.c*1000 + t2.c*100 + t1.c*10 + t0.c DAY) as `date`
from
(select 0 c union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) t0,
(select 0 c union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) t1,
(select 0 c union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) t2,
(select 0 c union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) t3,
(select 0 c union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) t4
Dat maakt een tabel met datums van 01-01-1900 tot 2173-10-15 (100.000 dagen) en verbruikt slechts ongeveer 2,5 MB. U kunt het aanpassen aan uw behoeften.
Met behulp van de kalendertabel kunt u bereiken van drie maanden:
select
DATE_FORMAT(date_sub(c.date, INTERVAL 1 day), '%Y-%m') as month,
date_sub(c.date, INTERVAL 3 month) as first_day,
date_sub(c.date, INTERVAL 1 day) as last_day
from calendar c
where day(c.date) = 1
and c.date between '2015-02-01' and '2015-09-01'
Resultaat:
| month | first_day | last_day |
| 2015-01 | 2014-11-01 | 2015-01-31 |
| 2015-02 | 2014-12-01 | 2015-02-28 |
| 2015-03 | 2015-01-01 | 2015-03-31 |
| 2015-04 | 2015-02-01 | 2015-04-30 |
| 2015-05 | 2015-03-01 | 2015-05-31 |
| 2015-06 | 2015-04-01 | 2015-06-30 |
| 2015-07 | 2015-05-01 | 2015-07-31 |
| 2015-08 | 2015-06-01 | 2015-08-31 |
Pas het aan als je echt intervallen van 90 dagen wilt gebruiken.
Nu is het een simpele left join met de login tabel om te krijgen wat je wilt:
select i.month as `Date`, count(distinct l.user_id) as `Active users`
from (
select
date_format(date_sub(c.date, interval 1 day), '%Y-%m') as month,
date_sub(c.date, interval 3 month) as first_day,
date_sub(c.date, interval 1 day) as last_day
from calendar c
where day(c.date) = 1
and c.date between '2015-02-01' and '2015-09-01'
) i
left join login_table l on l.login_date between i.first_day and i.last_day
group by i.month
http://sqlfiddle.com/#!9/d1bb0/3