Выбор строк на основе предыдущего периода — сохраненные пользователи

#sql #google-bigquery

#sql #google-bigquery

Вопрос:

Я пытаюсь определить список пользователей, которые были активны в период1, а также активны в период2 — по сути, это способ расчета удержания пользователей. Это данные, которые у меня есть

введите описание изображения здесь

И я хотел бы получить только пользователей / или иметь индикатор для каждой строки, если пользователь также появляется в предыдущем периоде. Период в этом случае составляет 3 дня. Наконец, я хотел бы определить, есть ли у пользователя запись (для любой строки), есть ли другая запись за 3 дня до этого. Я пробовал самосоединение, но, похоже, это работает только с точными датами, а не при наличии несогласованного временного шаблона.

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

Каков наилучший способ решить эту проблему, является ли самосоединение с временными рамками опцией?

Спасибо.

 WITH data1 as (
  SELECT DATE("2021-01-02") date, 'abc' user UNION ALL
  SELECT DATE("2021-01-03") date, 'abc' user UNION ALL
  SELECT DATE("2021-01-04") date, 'abc' user UNION ALL
  SELECT DATE("2021-01-09") date, 'abc' user UNION ALL
  SELECT DATE("2021-01-10") date, 'abc' user UNION ALL
  SELECT DATE("2021-01-11") date, 'abc' user UNION ALL   
  SELECT DATE("2021-01-04") date, 'aaa' user UNION ALL
  SELECT DATE("2021-01-09") date, 'aaa' user UNION ALL
  SELECT DATE("2021-01-10") date, 'aaa' user 
)

SELECT  
  data1.*
FROM data1 as data1
JOIN data1 as data_forward
  ON data1.user = data_forward.user
  AND data1.date = DATE_ADD(data_forward.date, INTERVAL 2 DAY)
 

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

1. Пожалуйста, предоставьте примеры результатов. Как измеряются три дня? С первого появления пользователя?

Ответ №1:

Рассмотрим ниже

 select date, user, 
  count(1) over period2 > 0 is_in_period2
from data1
window period2 as (
  partition by user 
  order by unix_date(date)
  range between 3 preceding and 1 preceding
)    
 

если применить к образцу данных в вашем вопросе — вывод

введите описание изображения здесь

Примечание: период2 в приведенном выше — считается тремя предыдущими днями — вы можете управлять этим в соответствующем выражении ниже

 range between 3 preceding and 1 preceding
 

Ответ №2:

Если вы хотите просмотреть 3 дня для каждой строки, то я думаю, что самый простой метод — это просто lag() :

 select t.*,
       ( lag(date) over (partition by user order by date) >= date_add(date, interval -3 day)
       ) as is_in_previous_period
from t;
 

lag() просматривает непосредственно предшествующую строку для пользователя. Если дата в этой строке находится в пределах 3 дней, то флаг равен TRUE .