Mysql
 sql >> Database >  >> RDS >> Mysql

Conta gli utenti attivi in ​​base agli accessi degli ultimi 90 giorni

Problemi come questo sono più facili da risolvere, se hai una tabella del calendario con tutte le date di cui hai bisogno. Se non hai una tabella del genere puoi crearla con una query come questa:

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

Ciò creerà una tabella con date dal 1900-01-01 al 2173-10-15 (100.000 giorni) e consumerà solo circa 2,5 MB. Puoi adattarlo alle tue esigenze.

Utilizzando la tabella del calendario puoi ottenere intervalli di tre mesi:

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'

Risultato:

| 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 |

Regolalo, se vuoi davvero usare qualcosa come intervalli di 90 giorni.

Ora è un semplice join sinistro con la tabella di accesso per ottenere ciò che desideri:

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