Questa query è modificata da quella che ho scritto qui:Analisi di coorte in SQL
Ecco la domanda finale:
SELECT
STR_TO_DATE(CONCAT(tb.cohort, ' Monday'), '%X-%V %W') as date,
size,
w1,
w2,
w3,
w4,
w5,
w6,
w7
FROM (
SELECT u.cohort,
IFNULL(SUM(s.Offset = 0), 0) w1,
IFNULL(SUM(s.Offset = 1), 0) w2,
IFNULL(SUM(s.Offset = 2), 0) w3,
IFNULL(SUM(s.Offset = 3), 0) w4,
IFNULL(SUM(s.Offset = 4), 0) w5,
IFNULL(SUM(s.Offset = 5), 0) w6,
IFNULL(SUM(s.Offset = 6), 0) w7
FROM (
SELECT
UserId,
DATE_FORMAT(AddedDate, "%Y-%u") AS cohort
FROM users
) as u
LEFT JOIN (
SELECT DISTINCT
payments.UserId,
FLOOR(DATEDIFF(payments.PaymentDate, users.AddedDate)/7) AS Offset
FROM payments
LEFT JOIN users ON (users.UserId = payments.UserId)
) as s ON s.UserId = u.UserId
GROUP BY u.cohort
) as tb
LEFT JOIN (
SELECT DATE_FORMAT(AddedDate, "%Y-%u") dt, COUNT(*) size FROM users GROUP BY dt
) size ON tb.cohort = size.dt
Quindi il fulcro di questo è che prendiamo gli utenti e la data in cui si sono registrati e formattiamo la data per numero di anno-settimana, dal momento che stiamo facendo una coorte settimanale.
SELECT
UserId,
DATE_FORMAT(AddedDate, "%Y-%u") AS cohort
FROM users
Dal momento che vogliamo raggruppare per coorte, dobbiamo inserirlo in una sottoquery nella parte FROM della query.
Quindi vogliamo unire le informazioni di pagamento sugli utenti.
SELECT DISTINCT
payments.UserId,
FLOOR(DATEDIFF(payments.PaymentDate, users.AddedDate)/7) AS Offset
FROM payments
LEFT JOIN users ON (users.UserId = payments.UserId)
Ciò otterrà eventi di pagamento settimanali unici per utente in base al numero di settimane in cui sono stati utenti. Usiamo distinti perché se un utente ha effettuato 2 acquisti in una settimana, non vogliamo conteggiarli come due utenti.
Non utilizziamo solo la tabella dei pagamenti, perché alcuni utenti potrebbero registrarsi e non avere pagamenti. Quindi selezioniamo dalla tabella degli utenti e ci uniamo alla tabella dei pagamenti.
Quindi raggruppa per settimana - u.cohort. Quindi aggreghi i numeri della settimana per scoprire quante persone hanno effettuato pagamenti nelle settimane successive alla registrazione.
La versione di mysql che ho usato aveva sql_mode impostata su only_full_group_by. Quindi, per ottenere la dimensione della coorte, ho inserito la maggior parte della query nella sottoquery in modo da potermi unire agli utenti per ottenere la dimensione della coorte.
Ulteriori considerazioni:
Filtrare per settimane è semplice. tb.cohort> data di inizio e tb.cohort
Potresti prendere in considerazione l'utilizzo di una tabella del calendario per coprire i casi in cui non ci sono registrazioni di utenti durante la settimana.
Ecco un piccolo assaggio con tutto ciò che funziona:http://sqlfiddle.com/#!9/172dbe/ 1