Когортный анализ удержания SQL - PullRequest
0 голосов
/ 12 апреля 2019

Я пытаюсь написать запрос на ежемесячное удержание, чтобы рассчитать процент пользователей, вернувшихся с начального месяца и продвигающихся вперед.

TABLE: customer_order
fields
id
date
store_id

TABLE: customer
id
person_id
job_id
first_time (bool)

Это дает мне начальные месячные когорты, основанные на первых датах

SELECT first_job_month, COUNT( DISTINCT person_id) user_counts
FROM 
   ( SELECT DATE_TRUNC(MIN(CAST(date AS DATE)), month) first_job_month, person_id
FROM customer_order cd
INNER JOIN consumer co ON co.job_id = cd.id
GROUP BY 2
ORDER BY 1 ) first_d GROUP BY 1 ORDER BY 1

first_job_month   user_counts
2018-04-01        36

2018-05-01        37

2018-06-01        39

2018-07-01        45

2018-08-01        38

Я перепробовал несколько вещей, но я не могу понять, как отследить оригинальных когорт / пользователей с первого месяца и далее

1 Ответ

0 голосов
/ 12 апреля 2019
  1. Получите ваш первый месяц заказа для каждого клиента
  2. Объедините заказы с предыдущим подзапросом, чтобы выяснить разницу в месяцах между данным заказом и первым заказом
  3. Использование условных агрегатов для подсчета клиентов, которые все еще заказывают к X месяцу

Есть несколько альтернативных вариантов, таких как использование оконных функций для выполнения (1) и (2) в одном и том же подзапросе, но самый простой вариант это:

WITH
cohorts as (
    SELECT person_id, DATE_TRUNC(MIN(CAST(date AS DATE)), month) as first_job_month
    FROM customer_order cd
    JOIN consumer co 
    ON co.job_id = cd.id
    GROUP BY 1
)
,orders as (
    SELECT
     *
    ,round(1.0*(DATE_TRUNC(MIN(CAST(cd.date AS DATE))-c.first_job_month)/30) as months_since_first_order
    FROM cohorts c
    JOIN customer_order cd
    USING (person_id)
)
SELECT
 first_job_month as cohort
,count(distinct person_id) as size
,count(distinct case when months_since_first_order>=1 then person_id end) as m1
,count(distinct case when months_since_first_order>=2 then person_id end) as m2
,count(distinct case when months_since_first_order>=3 then person_id end) as m3
-- hardcode up to the number of months you want and the history you have
FROM orders 
GROUP BY 1
ORDER BY 1

Видите, вы можете использовать операторы CASE внутри агрегатных функций, например COUNT, чтобы идентифицировать различные подмножества строк, которые вы хотите объединить в одной группе. Это один из наиболее важных методов BI в SQL.

Обратите внимание, что >= не = используется в условном агрегате, так что, например, если клиент покупает в m3 после m1 и не покупает в m2, они все равно будут учитываться в m2. Если вы хотите, чтобы ваши клиенты покупали каждый месяц и / или видели фактическое удержание за каждый месяц, и в порядке, если значения последующих месяцев могут быть выше, чем предыдущие, вы можете использовать =.

Кроме того, если вам не нужен «треугольный» вид, подобный тому, который вы получаете из этого запроса, или вы не хотите жестко кодировать часть «mX», вы просто сгруппируете по first_job_month и months_since_first_order и посчитаете различны. Некоторые инструменты визуализации могут использовать этот простой формат и создавать из него треугольник.

...