Cette requête est modifiée par rapport à celle que j'ai écrite ici :Analyse de cohorte en SQL
Voici la requête 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
Donc, le cœur de ceci est que nous saisissons les utilisateurs et la date à laquelle ils se sont inscrits et formatons la date par numéro d'année-semaine, puisque nous faisons une cohorte hebdomadaire.
SELECT
UserId,
DATE_FORMAT(AddedDate, "%Y-%u") AS cohort
FROM users
Puisque nous voulons regrouper par cohorte, nous devons mettre cela dans une sous-requête dans la partie FROM de la requête.
Ensuite, nous voulons joindre les informations de paiement sur les utilisateurs.
SELECT DISTINCT
payments.UserId,
FLOOR(DATEDIFF(payments.PaymentDate, users.AddedDate)/7) AS Offset
FROM payments
LEFT JOIN users ON (users.UserId = payments.UserId)
Cela obtiendra des événements de paiement hebdomadaires uniques par utilisateur en fonction du nombre de semaines d'utilisation. Nous utilisons distinct car si un utilisateur a effectué 2 achats en une semaine, nous ne voulons pas compter cela comme deux utilisateurs.
Nous n'utilisons pas seulement le tableau des paiements, car certains utilisateurs peuvent s'inscrire et ne pas avoir de paiements. Nous sélectionnons donc dans la table des utilisateurs et rejoignons la table des paiements.
Vous regroupez ensuite à la semaine - u.cohort. Ensuite, vous regroupez les chiffres de la semaine pour savoir combien de personnes ont effectué des paiements dans les semaines suivant leur inscription.
La version de mysql que j'ai utilisée avait sql_mode défini sur only_full_group_by. Donc, pour obtenir la taille de la cohorte, j'ai mis l'essentiel de la requête en sous-requête afin de pouvoir rejoindre les utilisateurs pour obtenir la taille de la cohorte.
Autres considérations :
Filtrer par semaines est simple. tb.cohort> date de début et tb.cohort
Vous pouvez envisager d'utiliser un tableau de calendrier pour couvrir les cas où aucun utilisateur ne s'inscrit pendant la semaine.
Voici un violon avec tout ce qui fonctionne :http://sqlfiddle.com/#!9/172dbe/ 1