このクエリは、私がここに書いたものから変更されています: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)
これにより、ユーザーがユーザーであった週数に応じて、ユーザーごとに固有の毎週の支払いイベントが発生します。ユーザーが1週間に2回購入した場合、それを2人のユーザーとしてカウントしたくないため、distinctを使用します。
一部のユーザーはサインアップして支払いを行わない可能性があるため、支払いテーブルを使用するだけではありません。したがって、usersテーブルから選択し、paymentsテーブルに参加します。
次に、週ごとにグループ化します-u.cohort。次に、週数を集計して、登録してから数週間後に支払いを行った人の数を調べます。
私が使用したmysqlのバージョンでは、sql_modeがonly_full_group_byに設定されていました。したがって、コホートのサイズを取得するために、クエリの大部分をサブクエリに入れて、ユーザーに参加してコホートのサイズを取得できるようにしました。
その他の考慮事項:
週でフィルタリングするのは簡単です。 tb.cohort>開始日およびtb.cohort<終了日。開始日と終了日は「%Y-%u」でフォーマットされます。クエリをより効率的にするには、日付範囲に含まれない支払いイベントも除外して、不要なデータに参加しないようにする必要があります。
週の間にユーザーの登録がない場合をカバーするために、カレンダーテーブルの使用を検討することをお勧めします。
これがすべてが機能しているフィドルです: http://sqlfiddle.com/#!9/172dbe/ 1