Тази заявка е променена от тази, която написах тук:Кохортен анализ в SQL
Ето последната заявка:
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
И така, сърцевината на това е, че вземаме потребителите и датата, на която са се регистрирали, и форматираме датата по номер година-седмица, тъй като правим седмична кохорта.
SELECT
UserId,
DATE_FORMAT(AddedDate, "%Y-%u") AS cohort
FROM users
Тъй като искаме да групираме по кохортата, трябва да поставим това в подзаявка в частта FROM на заявката.
След това искаме да присъединим информацията за плащане на потребителите.
SELECT DISTINCT
payments.UserId,
FLOOR(DATEDIFF(payments.PaymentDate, users.AddedDate)/7) AS Offset
FROM payments
LEFT JOIN users ON (users.UserId = payments.UserId)
Това ще получи уникални седмични плащания на потребител по броя на седмиците, през които е бил потребител. Използваме различни, защото ако потребител направи 2 покупки за една седмица, не искаме да ги броим като двама потребители.
Ние не използваме само таблицата за плащания, защото някои потребители може да се регистрират и да нямат плащания. Затова избираме от таблицата на потребителите и се присъединяваме към таблицата за плащания.
След това групирате по седмица - u.cohort. След това обобщавате числата за седмиците, за да разберете колко хора са направили плащания в седмиците след като са се регистрирали.
Версията на mysql, която използвах, имаше sql_mode, зададен на only_full_group_by. Така че, за да получа размера на кохортата, поставих по-голямата част от заявката в подзаявка, за да мога да се присъединя към потребителите, за да получа размера на кохортата.
Допълнителни съображения:
Филтрирането по седмици е лесно. tb.cohort> начална дата и tb.cohort <крайна дата, където началната и крайната дата са форматирани с "%Y-%u". За да направите заявката по-ефективна, вероятно ще искате да филтрирате и събития за плащане, които не попадат в диапазона от време, така че да не се присъединявате към данни, от които не се нуждаете.
Може да помислите за използването на таблица с календар, за да покриете случаите, при които няма регистрирани потребители през седмицата.
Ето една цигулка с всичко, което работи:http://sqlfiddle.com/#!9/172dbe/ 1