Активация активных пользователей, которые также были активны в предыдущие дни в bigquery - PullRequest
1 голос
/ 09 апреля 2019

Я хотел бы рассчитать текущее число активных пользователей, которые также были активными x или более раз за предыдущие y дней. Для простоты скажем> 3 раза за 5 дней

У меня есть данные

|    date   | user_id   |
------------------
|2019-01-01 | user1     |
|2019-01-01 | user2     |
|2019-01-01 | user1     |
|2019-01-02 | user1     |
|2019-01-02 | user3     |
|2019-01-02 | user4     |
|2019-01-03 | user2     |
|2019-01-03 | user3     |

Я пытался использовать агрегатные функции для группировки user_id по дате, а наличие оконной функции суммирует пользователей, которые существуют> 3 раза в 5 предыдущих строках. Агрегировать пользователей по дате можно, используя:

SELECT date, ARRAY_AGG(distinct user_id) as users
FROM `table` 
WHERE date > DATE_SUB(CURRENT_DATE(), INTERVAL 30 DAY)
GROUP BY date

Возвращение структуры массива, как это.

|    date   | users     |
------------------
|2019-01-01 | user1     |
|           | user2     |
|2019-01-02 | user1     |
|           | user3     |
|           | user4     |
|2019-01-03 | user2     |
|           | user3     |

Но здесь я застрял. Могу ли я сделать что-то подобное? Но какую аналитическую функцию я должен использовать?

WITH activity as (
  SELECT date, ARRAY_AGG(distinct user_id) as users
  FROM `table` 
  WHERE date > DATE_SUB(CURRENT_DATE(), INTERVAL 30 DAY)
  GROUP BY date
)

SELECT date, xxxx OVER (PARTITION BY date ORDER BY date ROWS 5 PRECEDING) as returning_users
FROM activity

Вывод, который я хотел бы получить:

|    date   | returning_users  |
------------------
|2019-01-01 | 123              |
|2019-01-02 | 1234             |
|2019-01-03 | 12345            |

1 Ответ

0 голосов
/ 12 апреля 2019

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

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

WITH ACTIVE_DAYS AS (
  SELECT
    a.date,
    a.user_id,
    COUNT(DISTINCT b.date) AS ActiveDays
  FROM
    DATA a
  JOIN
    DATA b
  ON
    a.user_id = b.user_id
    AND b.date BETWEEN DATE_SUB(a.date, INTERVAL 5 DAY) AND DATE_SUB(a.date, INTERVAL 1 DAY)
  GROUP BY
    1,
    2)
SELECT
  a.date,
  COUNT(DISTINCT a.user_id) AS DAU,
  COUNT(DISTINCT (CASE WHEN b.ActiveDays >= 3 THEN a.user_id END)) AS DAU_Meet_Criteria
FROM
  DATA a
LEFT JOIN
  ACTIVE_DAYS b
ON
  a.date = b.date
  AND a.user_id = b.user_id
GROUP BY
  1
ORDER BY
  1

Путем редактирования функций date_sub и оператора case во втором операторе count(distinct... вы можете достичь некоторой альтернативной логики.

Надеюсь, это поможет.

...