Den här frågan är modifierad från den jag skrev här:Kohortanalys i SQL
Här är den sista frågan:
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
Så kärnan i detta är att vi tar tag i användarna och datumet de registrerade sig och formaterar datumet efter år-veckonummer, eftersom vi gör en veckokohort.
SELECT
UserId,
DATE_FORMAT(AddedDate, "%Y-%u") AS cohort
FROM users
Eftersom vi vill gruppera efter kohorten måste vi lägga detta i en underfråga i FRÅN-delen av frågan.
Då vill vi gå med i betalningsinformationen på användarna.
SELECT DISTINCT
payments.UserId,
FLOOR(DATEDIFF(payments.PaymentDate, users.AddedDate)/7) AS Offset
FROM payments
LEFT JOIN users ON (users.UserId = payments.UserId)
Detta kommer att få unika veckobetalningshändelser per användare efter antalet veckor som de har varit användare. Vi använder distinkt eftersom om en användare gjorde två köp på en vecka vill vi inte räkna det som två användare.
Vi använder inte bara betalningstabellen, eftersom vissa användare kan registrera sig och inte ha betalningar. Så vi väljer från användartabellen och går med på betalningsbordet.
Man grupperar sedan efter vecka - u.cohort. Sedan sammanställer du veckonummer för att ta reda på hur många personer som gjorde betalningar veckorna efter att de registrerade sig.
Den version av mysql jag använde hade sql_mode inställd på only_full_group_by. Så för att få kohortens storlek placerade jag huvuddelen av frågan i underfrågan så att jag kunde gå med på användarna för att få storleken på kohorten.
Ytterligare överväganden:
Filtrera efter veckor är enkelt. tb.cohort> startdatum och tb.cohort
Du kanske vill överväga att använda en kalendertabell för att täcka fall där det inte finns några användarregistreringar under veckan.
Här är en fiol där allt fungerar:http://sqlfiddle.com/#!9/172dbe/ 1