To zapytanie jest zmodyfikowane od tego, które napisałem tutaj:Analiza kohortowa w SQL
Oto ostatnie zapytanie:
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
Więc sednem tego jest to, że zbieramy użytkowników i datę ich rejestracji i formatujemy datę według liczby rok-tydzień, ponieważ robimy cotygodniową kohortę.
SELECT
UserId,
DATE_FORMAT(AddedDate, "%Y-%u") AS cohort
FROM users
Ponieważ chcemy grupować według kohorty, musimy umieścić to w podzapytaniu w części FROM zapytania.
Następnie chcemy dołączyć informacje o płatnościach na użytkownikach.
SELECT DISTINCT
payments.UserId,
FLOOR(DATEDIFF(payments.PaymentDate, users.AddedDate)/7) AS Offset
FROM payments
LEFT JOIN users ON (users.UserId = payments.UserId)
Dzięki temu uzyskasz unikalne cotygodniowe zdarzenia dotyczące płatności na użytkownika według liczby tygodni, w których był użytkownikiem. Używamy odrębnego, ponieważ jeśli użytkownik dokonał 2 zakupów w ciągu tygodnia, nie chcemy liczyć tego jako dwóch użytkowników.
Nie używamy tylko tabeli płatności, ponieważ niektórzy użytkownicy mogą się zarejestrować i nie mieć płatności. Wybieramy więc z tabeli użytkowników i dołączamy do tabeli płatności.
Następnie grupujesz według tygodnia - u.cohort. Następnie łączysz numery tygodni, aby dowiedzieć się, ile osób dokonało płatności w kilka tygodni po rejestracji.
Wersja mysql, której użyłem, miała tryb sql_mode ustawiony na only_full_group_by. Aby uzyskać rozmiar kohorty, umieściłem większość zapytania w podzapytaniu, abym mógł dołączyć do użytkowników, aby uzyskać rozmiar kohorty.
Dalsze rozważania:
Filtrowanie według tygodni jest proste. tb.cohort> data rozpoczęcia i tb.cohort
Możesz rozważyć użycie tabeli kalendarza, aby uwzględnić przypadki, w których w ciągu tygodnia nie ma rejestracji użytkowników.
Oto skrzypce ze wszystkim, co działa:http://sqlfiddle.com/#!9/172dbe/ 1