sql >> Base de Datos >  >> RDS >> Mysql

¿Cómo puedo crear una tabla de análisis de cohortes semanal usando mysql?

Esta consulta está modificada de la que escribí aquí:Análisis de cohortes en SQL

Aquí está la consulta final:

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

Entonces, el núcleo de esto es que capturamos a los usuarios y la fecha en que se registraron y formateamos la fecha por número de año-semana, ya que estamos haciendo una cohorte semanal.

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

Como queremos agrupar por cohorte, tenemos que poner esto en una subconsulta en la parte DESDE de la consulta.

Entonces queremos unir la información de pago de los usuarios.

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

Esto obtendrá eventos de pago semanales únicos por usuario por la cantidad de semanas que han sido usuarios. Usamos distinto porque si un usuario hizo 2 compras en una semana, no queremos contar eso como dos usuarios.

No solo usamos la tabla de pagos, porque algunos usuarios pueden registrarse y no tener pagos. Así que seleccionamos de la tabla de usuarios y nos unimos a la tabla de pagos.

Luego agrupa por semana - u.cohort. Luego agrega los números de la semana para averiguar cuántas personas hicieron pagos las semanas posteriores a su registro.

La versión de mysql que utilicé tenía sql_mode establecido en only_full_group_by. Entonces, para obtener el tamaño de la cohorte, puse la mayor parte de la consulta en la subconsulta para poder unirme a los usuarios para obtener el tamaño de la cohorte.

Otras consideraciones:

Filtrar por semanas es sencillo. tb.cohort> fecha de inicio y tb.cohort

Es posible que desee considerar el uso de una tabla de calendario para cubrir los casos en los que no hay registros de usuarios durante la semana.

Aquí hay un violín con todo funcionando:http://sqlfiddle.com/#!9/172dbe/ 1