sql >> Databasteknik >  >> RDS >> Mysql

Hur kan jag skapa en kohortanalystabell varje vecka med mysql?

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



  1. UNION ALL vs OR-villkor i SQL-serverfrågan

  2. MySQL flyttal jämförelse problem

  3. MySQL Prepare Statement - Maximal längd 1000 tecken

  4. Python &MySql:Unicode och kodning