sql >> Database >  >> RDS >> Mysql

Hoe kan ik een wekelijkse cohortanalysetabel maken met mysql?

Deze query is gewijzigd ten opzichte van degene die ik hier heb geschreven:Cohortanalyse in SQL

Dit is de laatste vraag:

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

Dus de kern hiervan is dat we de gebruikers en de datum waarop ze zich hebben aangemeld, pakken en de datum formatteren op jaar-weeknummer, aangezien we een wekelijkse cohort doen.

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

Omdat we willen groeperen op cohort, moeten we dit in een subquery plaatsen in het FROM-gedeelte van de query.

Dan willen we meedoen met de betalingsgegevens van de gebruikers.

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

Dit krijgt unieke wekelijkse betalingsgebeurtenissen per gebruiker op basis van het aantal weken dat ze een gebruiker zijn. We gebruiken onderscheidend omdat als een gebruiker 2 aankopen heeft gedaan in één week, we dat niet als twee gebruikers willen tellen.

We gebruiken niet alleen de betalingstabel, omdat sommige gebruikers zich kunnen aanmelden en geen betalingen hebben. Dus we selecteren uit de gebruikerstabel en voegen ons toe aan de betalingstabel.

Je groepeert dan per week - u.cohort. Vervolgens aggregeert u op de weeknummers om erachter te komen hoeveel mensen betalingen hebben gedaan in de weken nadat ze zich hebben aangemeld.

De versie van mysql die ik gebruikte had sql_mode ingesteld op only_full_group_by. Dus om de cohortgrootte te krijgen, plaatste ik het grootste deel van de query in subquery, zodat ik me bij de gebruikers kon voegen om de grootte van de cohort te krijgen.

Verdere overwegingen:

Filteren op weken is eenvoudig. tb.cohort> startdatum en tb.cohort

U kunt overwegen een kalendertabel te gebruiken om gevallen te dekken waarin zich door de week geen gebruikers hebben aangemeld.

Hier is een viool met alles werkend:http://sqlfiddle.com/#!9/172dbe/ 1



  1. IMAP &PHP - Ophalen van alle e-mails uit verzonden en inbox-mappen

  2. Kan .mdf-database niet bijwerken omdat de database alleen-lezen is (Windows-toepassing)

  3. export grote datatable data naar .csv-bestand in c# windows-toepassingen

  4. Oracle SQL - max() met NULL-waarden