Mysql
 sql >> Database >  >> RDS >> Mysql

Come posso creare una tabella di analisi di coorte settimanale usando mysql?

Questa query è modificata da quella che ho scritto qui:Analisi di coorte in SQL

Ecco la domanda 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

Quindi il fulcro di questo è che prendiamo gli utenti e la data in cui si sono registrati e formattiamo la data per numero di anno-settimana, dal momento che stiamo facendo una coorte settimanale.

SELECT
  UserId,
  DATE_FORMAT(AddedDate, "%Y-%u") AS cohort
FROM users

Dal momento che vogliamo raggruppare per coorte, dobbiamo inserirlo in una sottoquery nella parte FROM della query.

Quindi vogliamo unire le informazioni di pagamento sugli utenti.

SELECT DISTINCT
  payments.UserId,
  FLOOR(DATEDIFF(payments.PaymentDate, users.AddedDate)/7) AS Offset
  FROM payments
  LEFT JOIN users ON (users.UserId = payments.UserId)

Ciò otterrà eventi di pagamento settimanali unici per utente in base al numero di settimane in cui sono stati utenti. Usiamo distinti perché se un utente ha effettuato 2 acquisti in una settimana, non vogliamo conteggiarli come due utenti.

Non utilizziamo solo la tabella dei pagamenti, perché alcuni utenti potrebbero registrarsi e non avere pagamenti. Quindi selezioniamo dalla tabella degli utenti e ci uniamo alla tabella dei pagamenti.

Quindi raggruppa per settimana - u.cohort. Quindi aggreghi i numeri della settimana per scoprire quante persone hanno effettuato pagamenti nelle settimane successive alla registrazione.

La versione di mysql che ho usato aveva sql_mode impostata su only_full_group_by. Quindi, per ottenere la dimensione della coorte, ho inserito la maggior parte della query nella sottoquery in modo da potermi unire agli utenti per ottenere la dimensione della coorte.

Ulteriori considerazioni:

Filtrare per settimane è semplice. tb.cohort> data di inizio e tb.cohort

Potresti prendere in considerazione l'utilizzo di una tabella del calendario per coprire i casi in cui non ci sono registrazioni di utenti durante la settimana.

Ecco un piccolo assaggio con tutto ciò che funziona:http://sqlfiddle.com/#!9/172dbe/ 1