Deze query is gewijzigd ten opzichte van degene die ik hier heb geschreven:Cohortanalyse in SQL
Dit is de laatste vraag:
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
Dus de kern hiervan is dat we de gebruikers en de datum waarop ze zich hebben aangemeld, pakken en de datum formatteren op jaar-weeknummer, aangezien we een wekelijkse cohort doen.
SELECT
UserId,
DATE_FORMAT(AddedDate, "%Y-%u") AS cohort
FROM users
Omdat we willen groeperen op cohort, moeten we dit in een subquery plaatsen in het FROM-gedeelte van de query.
Dan willen we meedoen met de betalingsgegevens van de gebruikers.
SELECT DISTINCT
payments.UserId,
FLOOR(DATEDIFF(payments.PaymentDate, users.AddedDate)/7) AS Offset
FROM payments
LEFT JOIN users ON (users.UserId = payments.UserId)
Dit krijgt unieke wekelijkse betalingsgebeurtenissen per gebruiker op basis van het aantal weken dat ze een gebruiker zijn. We gebruiken onderscheidend omdat als een gebruiker 2 aankopen heeft gedaan in één week, we dat niet als twee gebruikers willen tellen.
We gebruiken niet alleen de betalingstabel, omdat sommige gebruikers zich kunnen aanmelden en geen betalingen hebben. Dus we selecteren uit de gebruikerstabel en voegen ons toe aan de betalingstabel.
Je groepeert dan per week - u.cohort. Vervolgens aggregeert u op de weeknummers om erachter te komen hoeveel mensen betalingen hebben gedaan in de weken nadat ze zich hebben aangemeld.
De versie van mysql die ik gebruikte had sql_mode ingesteld op only_full_group_by. Dus om de cohortgrootte te krijgen, plaatste ik het grootste deel van de query in subquery, zodat ik me bij de gebruikers kon voegen om de grootte van de cohort te krijgen.
Verdere overwegingen:
Filteren op weken is eenvoudig. tb.cohort> startdatum en tb.cohort
U kunt overwegen een kalendertabel te gebruiken om gevallen te dekken waarin zich door de week geen gebruikers hebben aangemeld.
Hier is een viool met alles werkend:http://sqlfiddle.com/#!9/172dbe/ 1