Расчет DAU / MAU для сегментов - PullRequest
0 голосов
/ 28 декабря 2018

Я написал следующий запрос для вычисления отношения DAU / MAU:

WITH dau AS
(
  SELECT TRUNC(created_at) AS created_at,
         CASE
           WHEN user_agent SIMILAR TO '%(Mobile|iPhone|iPod|iPad|Android)%' THEN 'non-desktop'
           ELSE 'desktop'
         END AS trafficsource,
         COUNT(DISTINCT member_id) AS dau
  FROM table ds
  WHERE ds.created_at BETWEEN '2017-01-01' AND '2017-12-11'
  AND   member_id <> 2
  AND   member_id NOT IN (SELECT memberid FROM auth2.membersinglerole WHERE roleid = 25)
  GROUP BY TRUNC(created_at),
           trafficsource
)
SELECT created_at,
       trafficsource,
       dau,
       (SELECT COUNT(DISTINCT member_id)
        FROM table ds
        WHERE member_id <> 2
        AND   member_id NOT IN (SELECT memberid FROM auth2.membersinglerole WHERE roleid = 25)
        AND   ds.created_at BETWEEN dau.created_at - 29*INTERVAL '1 day' AND dau.created_at) AS mau,
       (dau / CAST(mau AS float)) AS "DAU/MAU",
       (dau / CAST(mau AS float))*30 AS DaysOutOf30
FROM dau
WHERE EXTRACT(dayofweek FROM created_at) NOT IN (0,6)
AND   EXTRACT(month FROM created_at) NOT IN (5,6,7)
ORDER BY created_at

Этот запрос создает 2 сегмента для «рабочего стола» и «не рабочего стола».Но, в частности, запрос возвращает одинаковые номера «MAU» для обоих этих сегментов для одного и того же дня, как показано ниже.

created_at    trafficsource    dau    mau    DAU/MAU    DaysOutOf30
2017-01-02  desktop 4157    140834  0.02951702003777497 0.8855106011332491
2017-01-02  non-desktop 801 140834  0.005687547041197438    0.17062641123592315
2017-01-03  desktop 12610   140468  0.089771335820258   2.6931400746077396
2017-01-03  non-desktop 2891    140468  0.020581199988609505    0.6174359996582851
2017-01-04  non-desktop 4033    137516  0.029327496436778264    0.8798248931033479
2017-01-04  desktop 17902   137516  0.1301812152767678  3.9054364583030337

Как исправить запрос, чтобы он возвращал значения «MAU» для созданных сегментов?Любая помощь будет принята с благодарностью.

1 Ответ

0 голосов
/ 10 января 2019

Вы можете получить точное значение mau, рассчитав его отдельно, а затем присоединив его к dau для окончательного результата.

Логические шаги:

  1. Создать traffic с 1 строкой на member_id в день.Обратите внимание, что диапазон начинается на 30 дней раньше, чем ваш окончательный диапазон выбора.
  2. Создать dau, который в основном не изменился
  3. Создать mau, присоединив traffic к себе с объединением диапазона, которое(используя вашу интервальную логику) приносит данные за последние 30 дней.Посчитайте member_id по этим данным.
  4. Выберите окончательные данные, соединив dau и mau в created_at.

WITH traffic AS (
    SELECT member_id,
           TRUNC(created_at) AS created_at,
           CASE WHEN user_agent SIMILAR TO '%(Mobile|iPhone|iPod|iPad|Android)%' 
           THEN 'non-desktop' ELSE 'desktop' END AS trafficsource,
    FROM table ds
    WHERE ds.created_at BETWEEN '2016-12-01' AND '2017-12-11'
    AND   member_id <> 2
    AND   member_id NOT IN (SELECT memberid FROM auth2.membersinglerole WHERE roleid = 25)
    GROUP BY 1,2,3
), dau AS (
    SELECT created_at, trafficsource,
           COUNT(DISTINCT member_id) AS dau
    FROM traffic
    GROUP BY 1,2
), mau AS (
    SELECT ds.created_at, ds.trafficsource,
           COUNT(DISTINCT ds.member_id) AS mau
    FROM traffic ds
    LEFT JOIN traffic mth
        ON  ds.member_id = mth.member_id
        AND ds.created_at BETWEEN mth.created_at - 29*INTERVAL '1 day' AND mth.created_at
    GROUP BY 1,2
    )
SELECT created_at, trafficsource, dau, mau,
       (dau / CAST(mau AS float)) AS "DAU/MAU",
       (dau / CAST(mau AS float))*30 AS DaysOutOf30
FROM dau
JOIN mau    
    USING (created_at, trafficsource)
WHERE created_at BETWEEN '2017-01-01' AND '2017-12-11'
AND   EXTRACT(dayofweek FROM created_at) NOT IN (0,6)
AND   EXTRACT(month FROM created_at) NOT IN (5,6,7)
ORDER BY created_at
;
...