Microsegment.ru
  • Главная страница
  • О проекте
  • Портфолио
  • Блог

Исследование точек роста сервиса Всё.из.кафе с помощью PostgreSQL

Описание проекта

Получение данных из базы данных сервиса Всё.из.кафе для использования их в исследовании точек роста сервиса и построения для этого дашбордов в Tableau.

Описание данных

Используемые таблицы из БД проекта:

  • module3_analytics_events — таблица журнала (лог) аналитических событий. Сюда попадают данные о посещении пользователем страниц продукта и покупках;
  • module3_cities — таблица-справочник населённых пунктов, в которых можно пользоваться продуктом;
  • module3_partners — таблица-справочник партнёрских сетей и их ресторанов.

Таблица module3_analytics_events:

  • visitor_uuid — идентификатор посетителя. Он присваивается системой любому новому пользователю вне зависимости от того, зарегистрировался он в продукте или нет;
  • user_id — идентификатор зарегистрированного пользователя. Присваивается посетителю после создания учётной записи: ввода логина, пароля, адреса доставки и контактных данных;
  • device_type — тип платформы, с которой посетитель зашёл в продукт;
  • city_id — город, из которого посетитель зашёл в сервис;
  • age — возрастная группа пользователя (указывается при регистрации);
  • source — рекламный источник привлечения посетителя;
  • first_date — дата первого посещения продукта;
  • visit_id — уникальный идентификатор сессии;
  • event — название аналитического события;
  • datetime — дата и время события;
  • log_date — дата события;
  • rest_id — уникальный идентификатор ресторана (заполняется для заказов, карточек ресторанов и блюд);
  • object_id — уникальный идентификатор блюда (заполняется для заказов и карточек блюд);
  • listing_id — уникальный идентификатор блюда в листинге. Листинг — набор блюд, которые рекомендуются системой пользователю при просмотре страницы ресторана. Заполняется только для событий типа rest_page;.
  • position — позиция блюда в листинге. Чем меньше номер, тем ближе блюдо к началу страницы. Заполняется только для событий типа rest_page;
  • order_id — уникальный идентификатор заказа;
  • revenue — выручка от заказа, в рублях. Это та сумма, которую пользователь видит при оплате;
  • delivery — стоимость доставки, в рублях;
  • commission — комиссия, которую «Всё.из.кафе» берёт с выручки ресторана, в процентах
  • visit_num — порядковый номер сессии пользователя;
  • order_num — порядковый номер покупки, совершённой пользователем.

Таблица module3_cities:

  • city_id — уникальный идентификатор населённого пункта;
  • city_name — название населённого пункта.

Таблица module3_partners:

  • rest_id — уникальный идентификатор ресторана;
  • chain — название сети, к которой принадлежит ресторан;
  • type — тип кухни;
  • city_id — город, в котором находится ресторан;
  • commission — комиссия, которую «Всё.из.кафе» берёт с выручки ресторана, в процентах.

Содержание¶

  1. Распределение числа пользовательских сессий
  2. Распределение первых покупок по номерам сессий
  3. Изучение последовательности действий пользователей
  4. User journey
  5. RFM-анализ
  6. ABC-XYZ-анализ

1. Распределение числа пользовательских сессий ¶

Получение максимального числа сессий для каждого из пользователей, установивших продукт в период с 2021-06-15 по 2021-07-01. Построение распределения максимального числа сессий с разбивкой по типам устройств. В исследование user journey попадают и зарегистрированные, и незарегистрированные пользователи, то есть анализ проводится по visitor_uuid.

Перед изучением user journey полезно уточнить объём данных, участвующих в исследовании. Например, если пользователи не заходят в продукт более трёх раз, то путь стоит изучать только в рамках первых трёх сессий.

-- Профили пользователей
WITH profiles as (
    SELECT DISTINCT visitor_uuid,
           FIRST_VALUE(city_name) OVER (PARTITION BY visitor_uuid ORDER BY datetime) AS city_name,
           FIRST_VALUE(first_date) OVER (PARTITION BY visitor_uuid ORDER BY datetime) AS first_date,
           FIRST_VALUE(device_type) OVER (PARTITION BY visitor_uuid ORDER BY datetime) AS device_type,
           FIRST_VALUE(source) OVER (PARTITION BY visitor_uuid ORDER BY datetime) AS source
    FROM module3_analytics_events AS a
    LEFT JOIN module3_cities c ON a.city_id = c.city_id
    WHERE first_date BETWEEN '2021-06-15' AND '2021-07-01'
          AND visit_num = 1
),

-- Максимальное число сессий на пользователя 
sessions AS (
    SELECT visitor_uuid,
           MAX(visit_num) AS sessions_num
    FROM module3_analytics_events
    WHERE first_date BETWEEN '2021-06-15' AND '2021-07-01'
          AND log_date BETWEEN '2021-06-15' AND '2021-07-01'
    GROUP BY visitor_uuid
)

-- Профили пользователей и их сессии
SELECT p.device_type,
       s.sessions_num,
       COUNT(DISTINCT s.visitor_uuid) AS uniques
FROM sessions s
LEFT JOIN profiles p ON s.visitor_uuid = p.visitor_uuid
GROUP BY p.device_type,
         s.sessions_num
ORDER BY p.device_type,
         s.sessions_num;
device_type sessions_num uniques
Desktop 1 6240
Desktop 2 718
Desktop 3 171
Desktop 4 63
Desktop 5 19
Desktop 6 2
Deskto 8 5
Desktop 9 1
Desktop 13 1
Mobil 1 4948
Mobile 2 349
Mobile 3 54
Mobile 4 17
Mobile 5 4
Mobile 6 1
Mobile 9 1

2. Распределение первых покупок по номерам сессий ¶

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

-- Профили пользователей
WITH profiles as (
    SELECT DISTINCT visitor_uuid,
           FIRST_VALUE(c.city_name) OVER (PARTITION BY visitor_uuid ORDER BY datetime) AS city_name,
           FIRST_VALUE(a.first_date) OVER (PARTITION BY visitor_uuid ORDER BY datetime) AS first_date,
           FIRST_VALUE(a.device_type) OVER (PARTITION BY visitor_uuid ORDER BY datetime) AS device_type,
           FIRST_VALUE(a.source) OVER (PARTITION BY visitor_uuid ORDER BY datetime) AS source
    FROM module3_analytics_events AS a
    LEFT JOIN module3_cities c ON a.city_id = c.city_id
    WHERE first_date BETWEEN '2021-06-15' AND '2021-07-01'
          AND visit_num = 1

),

-- Покупки и их номера
orders AS (
    SELECT visitor_uuid,
           visit_num,
           DENSE_RANK() OVER (PARTITION BY visitor_uuid ORDER BY datetime) AS event_num
    FROM module3_analytics_events
    WHERE first_date BETWEEN '2021-06-15' AND '2021-07-01'
          AND log_date BETWEEN '2021-06-15' AND '2021-07-01'
          AND event = 'order'
)

-- Расчёт медиан
SELECT p.device_type,
       COUNT (DISTINCT o.visitor_uuid) AS buyers,
       PERCENTILE_CONT(.5) WITHIN GROUP (ORDER BY o.visit_num) AS median_visit_num
FROM orders o
LEFT JOIN profiles p ON o.visitor_uuid = p.visitor_uuid
WHERE o.event_num = 1
GROUP BY p.device_type
ORDER BY buyers DESC;
device_type buyers median_visit_num
Desktop 458 1
Mobile 226 1

3. Изучение последовательности действий пользователей ¶

Анализ последовательности действий, совершаемых пользователем в рамках первой сессии. Результат выполнения запроса содержит:

  • Наименование аналитического события.
  • Номер аналитического события в цепочке событий, совершённых каждым из пользователей.
  • Число пользователей, совершивших событие. Например, если у 100 пользователей первым было событие authorization, вторым — main_page, а третьим — order, то должна получиться таблица:
authorization 1 100
main_page 2 100
order 3 100

К результату добавлена разбивка по городам, датам и источникам привлечения пользователей, а также по типам устройств. Для каждого пользователя получены первые 10 событий.

-- Профили пользователей
WITH profiles as (
    SELECT DISTINCT visitor_uuid,
           FIRST_VALUE(c.city_name) OVER (PARTITION BY visitor_uuid ORDER BY datetime) AS city_name,
           FIRST_VALUE(a.first_date) OVER (PARTITION BY visitor_uuid ORDER BY datetime) AS first_date,
           FIRST_VALUE(a.device_type) OVER (PARTITION BY visitor_uuid ORDER BY datetime) AS device_type,
           FIRST_VALUE(a.source) OVER (PARTITION BY visitor_uuid ORDER BY datetime) AS source
    FROM module3_analytics_events AS a
    LEFT JOIN module3_cities c ON a.city_id = c.city_id
    WHERE first_date BETWEEN '2021-06-15' AND '2021-07-01'
          AND visit_num = 1
),

-- События, совершённые пользователями за первую сессию, и их номера
events AS (
    SELECT visitor_uuid,
           visit_num,
           event,
           DENSE_RANK() OVER (PARTITION BY visitor_uuid ORDER BY datetime) AS event_num
    FROM module3_analytics_events
    WHERE first_date BETWEEN '2021-06-15' AND '2021-07-01'
          AND log_date BETWEEN '2021-06-15' AND '2021-07-01'
          AND visit_num = 1
),

-- События и профили вместе
events_profiles AS (
    SELECT e.visitor_uuid,
           p.city_name,
           p.first_date,
           p.device_type,
           p.source,
           visit_num,
           event,
           event_num
    FROM events e
    LEFT JOIN profiles p ON e.visitor_uuid = p.visitor_uuid
)

-- Финальные вычисления
SELECT city_name,
       first_date,
       device_type,
       source,
       visit_num,
       event_num,
       event,
       COUNT(visitor_uuid) AS events
FROM events_profiles
WHERE event_num <= 10
GROUP BY city_name,
         first_date,
         device_type,
         source,
         visit_num,
         event_num,
         event;
city_name first_date device_type source visit_num event_num event events
Новосибирск 2021-06-25 Mobile Source_B 1 6 main_page 22
Новосибирск 2021-06-24 Mobile organic 1 6 login 1
Новосибирск 2021-06-24 Desktop Source_B 1 7 confirm_phone 1
Мурино 2021-06-21 Desktop organic 1 3 main_page 24
Саранск 2021-06-27 Desktop Source_B 1 8 rest_page 3
Владивосток 2021-06-19 Desktop Source_C 1 1 reg_page 1
Саранск 2021-07-01 Mobile organic 1 4 reg_page 1
Владивосток 2021-06-18 Mobile Source_B 1 2 main_page 1
Сочи 2021-06-23 Mobile organic 1 7 object_page 1
… … … … … … … …

4. User journey ¶

Запрос для формирования user journey и его визуализации в Tableau. Запрос возвращает:

  • Идентификатор пользователя.
  • Наименование аналитического события.
  • Минимальный лайфтайм в минутах от момента первого входа в продукт до наступления аналитического события.

Для каждого пользователя добавлен город, дата и источник привлечения, а также тип устройства.

-- Профили пользователей
WITH profiles as (
    SELECT DISTINCT visitor_uuid,
           FIRST_VALUE(c.city_name) OVER (PARTITION BY visitor_uuid ORDER BY datetime) AS city_name,
           FIRST_VALUE(a.datetime) OVER (PARTITION BY visitor_uuid ORDER BY datetime) AS first_datetime,
           FIRST_VALUE(a.first_date) OVER (PARTITION BY visitor_uuid ORDER BY datetime) AS first_date,
           FIRST_VALUE(a.device_type) OVER (PARTITION BY visitor_uuid ORDER BY datetime) AS device_type,
           FIRST_VALUE(a.source) OVER (PARTITION BY visitor_uuid ORDER BY datetime) AS source
    FROM module3_analytics_events AS a
    LEFT JOIN module3_cities c ON a.city_id = c.city_id
    WHERE first_date BETWEEN '2021-06-15' AND '2021-07-01'
          AND visit_num = 1

),

-- События, совершённые пользователями за первую сессию
events AS (
    SELECT visitor_uuid,
           event,
           datetime
    FROM module3_analytics_events
    WHERE first_date BETWEEN '2021-06-15' AND '2021-07-01'
          AND log_date BETWEEN '2021-06-15' AND '2021-07-01'
          AND visit_num = 1
)

-- Профили, события и время их наступления
SELECT e.visitor_uuid,
       p.city_name,
       p.first_date,
       p.device_type,
       p.source,
       e.event,
       EXTRACT(epoch FROM MIN(e.datetime - p.first_datetime)) / 60 AS time_to_event
FROM events e
LEFT JOIN profiles p ON e.visitor_uuid = p.visitor_uuid
GROUP BY e.visitor_uuid,
         p.city_name,
         p.first_date,
         p.device_type,
         p.source,
         e.event;
visitor_uuid city_name first_date device_type source event time_to_event
00015d39-ace9-4976-b3d6-e647b4aee83f Новосибирск 2021-06-23 Mobile organic authorization 0
00015d39-ace9-4976-b3d6-e647b4aee83f Новосибирск 2021-06-23 Mobile organic main_page 1.93333
00015d39-ace9-4976-b3d6-e647b4aee83f Новосибирск 2021-06-23 Mobile organic reg_page 1.88333
0001ad5a-84b9-442b-a518-d1ea8d7a1cf0 Саранск 2021-06-17 Desktop organic authorization 0
0001ad5a-84b9-442b-a518-d1ea8d7a1cf0 Саранск 2021-06-17 Desktop organic main_page 0.25
0008137e-4841-4b94-9116-0f976e6f6142 Мурино 2021-06-18 Desktop organic authorization 0
0008137e-4841-4b94-9116-0f976e6f6142 Мурино 2021-06-18 Desktop organic main_page 0.0833333
… … … … … … …

5. RFM-анализ ¶

Подготовка данных для проведения RFM-анализа платящих пользователей в Tableau. Для каждого покупателя определены RFM-сегменты, город, дата и источник привлечения, а также тип устройства. Для исследования RFM-сегментации используется интервал регистрации пользователей с 2021-05-01 по 2021-06-01.

-- Профили пользователей
WITH profiles as (
    SELECT DISTINCT user_id,
           FIRST_VALUE(c.city_name) OVER (PARTITION BY user_id ORDER BY datetime) AS city_name,
           FIRST_VALUE(a.first_date) OVER (PARTITION BY user_id ORDER BY datetime) AS first_date,
           FIRST_VALUE(a.device_type) OVER (PARTITION BY user_id ORDER BY datetime) AS device_type,
           FIRST_VALUE(a.source) OVER (PARTITION BY user_id ORDER BY datetime) AS source
    FROM module3_analytics_events AS a
    LEFT JOIN module3_cities c ON a.city_id = c.city_id
    WHERE first_date BETWEEN '2021-05-01' AND '2021-06-01'
          AND user_id IS NOT NULL
),

-- Покупки пользователей
orders AS (
    SELECT 'dummy' AS dummy_key,
           user_id,
           MIN(DATE('2021-07-01') - log_date) AS recency,
           COUNT(log_date) AS frequency,
           SUM(revenue) AS monetary_value
    FROM module3_analytics_events
    WHERE first_date BETWEEN '2021-05-01' AND '2021-06-01'
          and event = 'order'
    GROUP BY user_id
),

-- Границы RFM-групп
boundaries AS (
    SELECT 'dummy' AS dummy_key,
           PERCENTILE_CONT(.33) WITHIN GROUP(ORDER BY recency) AS p33_recency,
           PERCENTILE_CONT(.66) WITHIN GROUP(ORDER BY recency) AS p66_recency,

           PERCENTILE_CONT(.33) WITHIN GROUP(ORDER BY frequency) AS p33_frequency,
           PERCENTILE_CONT(.66) WITHIN GROUP(ORDER BY frequency) AS p66_frequency,

           PERCENTILE_CONT(.33) WITHIN GROUP(ORDER BY monetary_value) AS p33_monetary_value,
           PERCENTILE_CONT(.66) WITHIN GROUP(ORDER BY monetary_value) AS p66_monetary_value
    FROM orders
),

-- Определение RFM-групп для пользователей
rfm AS (
    SELECT user_id,
           recency,
           frequency,
           monetary_value,
           p33_recency,
           p66_recency,
           p33_frequency,
           p66_frequency,
           p33_monetary_value,
           p66_monetary_value,
           CASE
                WHEN recency <= p33_recency THEN 3
                WHEN recency <= p66_recency AND recency > p33_recency THEN 2
                ELSE 1
           END AS r,
           CASE
                WHEN frequency <= p33_frequency THEN 1
                WHEN frequency <= p66_frequency AND frequency > p33_frequency THEN 2
                ELSE 3
           END AS f,
           CASE
                WHEN monetary_value <= p33_monetary_value THEN 1
                WHEN monetary_value <= p66_monetary_value AND monetary_value > p33_monetary_value THEN 2
                ELSE 3
           END AS m
    FROM orders o
    LEFT JOIN boundaries b ON b.dummy_key = o.dummy_key
)

-- Объединение RFM-групп с профилями
SELECT r.user_id,
       city_name,
       first_date,
       device_type,
       source,
       r, f, m
FROM rfm r
LEFT JOIN profiles p ON p.user_id = r.user_id;
user_id city_name first_date device_type source r f m
5210 Сочи 2021-05-05 Desktop Source_C 1 1 2
5506 Сочи 2021-05-04 Desktop Source_C 3 2 2
6291 Сочи 2021-05-06 Desktop organic 1 1 1
6820 Сочи 2021-05-22 Mobile Source_C 2 1 1
11062 Саранск 2021-05-06 Desktop organic 1 1 2
13254 Саранск 2021-05-09 Mobile Source_B 1 1 1
13319 Саранск 2021-05-06 Desktop Source_C 1 1 3
14394 Саранск 2021-05-08 Mobile Source_B 1 1 1
… … … … … … … …

6. ABC-XYZ-анализ ¶

Подготовка данных для проведения ABC-XYZ-анализа партнёрских сетей ресторанов в Tableau. Для каждой сети определены ABC- и XYZ-сегменты.

-- Рассчитываем недельную выручку сетей
WITH daily_revenue AS (
    SELECT p.chain,
           date_trunc('week', log_date) as log_week,
           SUM(revenue) AS revenue
    FROM module3_analytics_events e
    LEFT JOIN module3_partners p on p.rest_id = e.rest_id
    WHERE event = 'order'
    GROUP BY p.chain,
             date_trunc('week', log_date)
),

-- Рассчитываем коэффициенты вариативности
partners AS (
    SELECT chain,
           SUM(revenue) AS revenue,
           STDDEV(revenue) AS std,
           STDDEV(revenue) / AVG(revenue) AS var_coeff
    FROM daily_revenue
    GROUP BY chain

),

-- Рассчитываем доли от общей выручки
abc_xyz AS (
    SELECT chain,
           revenue,
           SUM(revenue) OVER (ORDER BY revenue DESC) AS cumulative_revenue,
           SUM(revenue) OVER () tot_rev,
           SUM(revenue) OVER (ORDER BY revenue DESC) / SUM(revenue) OVER () AS perc,
           std,
           var_coeff
    FROM partners
    ORDER BY revenue DESC

)

-- Распределяем партнёрские рестораны по группам
SELECT chain,
       CASE
           WHEN perc <= .8 THEN 'A' 
           WHEN perc <= .95 THEN 'B' 
           ELSE 'C'
       END AS abc,
       CASE
           WHEN var_coeff <= .1 THEN 'X' 
           WHEN var_coeff <= .3 THEN 'Y' 
           ELSE 'Z'
       END AS xyz
FROM abc_xyz;
chain abc xyz
Гурманское Наслаждение A Z
Гастрономический Шторм A Z
Шоколадный Рай A Z
Завтраки на любой вкус A Z
Завтрак на полную B Z
Утренний прием B Z
Салатный Лес B Z
Здоровый Шанс B Z
Ресторан Добрых Выборов B Z
Бутербродный Путешественник C Z
Завтраки на каждый день C Z
Венецианский Паб C Z
Мамма Миа C Z
Бутербродная Вселенная C Z
Сладкий Путь C Z
Кондитерская История C Z
Сэндвичный Парад C Z
Флорентийский Ресторан C Z
Невероятные Бутерброды C Z
Паста и Приятели C Z

Политика конфиденциальности

Продолжая использовать данный сайт вы подтверждаете свое согласие с условиями его политики конфиденциальности. Подробнее…




Администрация и владельцы данного информационного ресурса не несут ответственности за возможные последствия, связанные с использованием информации, размещенной на нем.


Все права защищены. При копировании материалов сайта обязательно указывать ссылку на © Microsegment.ru (2020-2025)