Как получить условный расчет, который я хочу, с помощью SQL

#sql #data-analysis

Вопрос:

У меня есть таблица с более чем 500 тысячами строк и столбцов, как показано ниже;

 user_id | event_date | event_name | version| ===============================================  1543435 | 18092021 | first_open | 113   5476523 | 18092021 | session_start| 111   7418529 | 18092021 | first_open | 112   1754821 | 18092021 | first_open | 113   9820011 | 18092021 | session_start| 114   4568714 | 18092021 | session_start| 120  

Пользователи, у которых есть имя события с first_open, означают, что пользователь установил и открыл приложение в первый раз, в то время как session_start означает, что пользователь установил и открыл его раньше, это не в первый раз.

идентификатор пользователя уникален для каждого пользователя и не меняется при каждом входе в систему.

Мы имеем дело с пользователями, у которых есть только версия 113.

Мне нужно найти долю пользователей, которые установили приложение 18-го числа (18.09.2021) и снова открыли его 1-го (19.09.2021) и 3-го (21.09.2021) дней.

Дорожная карта:

  • Шаг 1: Поиск уникальных идентификаторов пользователей с датой события=18092021 и именем события=first_open и получение их количества
  • Шаг 2: Поиск количества совпадений с датой события=19092021 и именем события=начало сеанса, которые также соответствуют идентификаторам пользователей из шага 1
  • Шаг 3: Поиск количества совпадений с датой события=21092021 и именем события=session_start, которые также соответствуют идентификаторам пользователей из шага 1
  • Шаг 4: Деление числа подсчета на шаге 2 и числа подсчета на шаге 1 даст нам задержку на 1 день
  • Шаг 5: Деление числа подсчета на шаге 3 и числа подсчета на шаге 1 даст нам удержание на 3-й день

После недели исследований и мозгового штурма я написал запрос ниже:

 SELECT  (SELECT COUNT(DISTINCT our_data.user_id) FROM our_data WHERE our_data.event_date = '20210918'  AND our_data.event_name ='first_open'  AND our_data.version = '113')  AS DAY_ZERO,  (SELECT COUNT(DISTINCT dayone.user_id)  FROM our_data LEFT JOIN our_data AS dayone  ON our_data.user_id = dayone.user_id) WHERE our_data.event_date = '20210918'  AND dayone.event_date = our_data.event_date  1 AND our_data.event_name ='first_open'  AND dayone.event_name ='session_start'  AND our_data.version = '113'  AND dayone.version = '113') AS DAY_ONE,  (SELECT COUNT(DISTINCT our_data.user_id) FROM our_data LEFT JOIN our_data as daythree ON our_data.user_id = daythree.user_id  WHERE our_data.event_date = '20210918'  AND daythree.event_date = our_data.event_date  3 AND our_data.event_name ='first_open'  AND daythree.event_name ='session_start'  AND our_data.version = '113'  AND daythree.version = '113') AS DAY_THREE  

Этот запрос дал мне следующие результаты:

 DAY_ZERO | DAY_ONE | DAY_THREE | ========================================  14879 | 7850 | 949 |   

Среди этих результатов я не смог выполнить ни одной операции в одном и том же запросе. Мне нужно достичь Day_ONE/DAY_ZERO= УДЕРЖАНИЕ на 1-й ДЕНЬ и DAY_THREE/DAY_ZERO= УДЕРЖАНИЕ НА 3-Й ДЕНЬ. Мне нужно выполнить эти операции в течение других первых дней в той же таблице, поэтому я должен сделать это в одном запросе. Как ты думаешь, что я могу сделать?

Комментарии:

1. Я удалил конфликтующие теги СУБД. Просто отметьте тот, который вы действительно используете.

Ответ №1:

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

 select   DAY_ONE/DAY_ZERO as DAY_1_RETENTION,  DAY_THREE/DAY_ZERO as DAY_3_RETENTION from (... your query ...)  

Комментарии:

1. Я попытался сделать это сейчас, но получил предупреждения «Недопустимое имя столбца» для каждого DAY_ZERO, DAY_ONE и DAY_THREE.

Ответ №2:

Я бы опубликовал это в комментарии, но запрос кажется слишком длинным для комментария. Короче говоря, лучший ответ будет немного зависеть от того, какой тип SQL вы на самом деле используете (T-SQL? PL/SQL? PL/pgSQL?), но общий подход будет таким же.

Вы уже рассчитали необходимые значения в подзапросах. Я повторно использовал эти подзапросы, но вместо значений строк превратил их в таблицы с уникальными именами столбцов.

Теперь у вас есть три таблицы, каждая из которых имеет одну строку. Скрестите их, чтобы получить «одну строку» с тремя разными столбцами… и выполните необходимые вычисления по столбцам

 select   DAY_ONE.cnt1/DAY_ZERO.cnt0 as DAY_1_RETENTION,  DAY_THREE.cnt3/DAY_ZERO.cnt0 as DAY_3_RETENTION FROM (SELECT COUNT(DISTINCT our_data.user_id) AS cnt0  FROM our_data WHERE our_data.event_date = '20210918'   AND our_data.event_name ='first_open'   AND our_data.version = '113')   AS DAY_ZERO,   (SELECT COUNT(DISTINCT dayone.user_id) cnt1  FROM our_data  LEFT JOIN our_data AS dayone   ON our_data.user_id = dayone.user_id)  WHERE our_data.event_date = '20210918'   AND dayone.event_date = our_data.event_date  1  AND our_data.event_name ='first_open'   AND dayone.event_name ='session_start'   AND our_data.version = '113'   AND dayone.version = '113')  AS DAY_ONE,   (SELECT COUNT(DISTINCT our_data.user_id) cnt3  FROM our_data  LEFT JOIN our_data as daythree  ON our_data.user_id = daythree.user_id   WHERE our_data.event_date = '20210918'   AND daythree.event_date = our_data.event_date  3  AND our_data.event_name ='first_open'   AND daythree.event_name ='session_start'   AND our_data.version = '113'   AND daythree.version = '113')  AS DAY_THREE  

Комментарии:

1. это работает как заклинание! большое вам спасибо за потраченное время.