2016-10-28 10 views
2

Я пытаюсь найти отличное количество пользователей из США, которые выполнили конкретное действие (любая строка в p.action) в течение 14-дневного скользящего окна , за последние 2 месяца.Как удалить коррелированный подзапрос в моем подзапросе (из-за предварительного ограничения)

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

SELECT dt, 
    (SELECT COUNT(DISTINCT user_id) 
    FROM p.action 
    WHERE dt BETWEEN q.dt - 13 AND q.dt -- period of 14 days 
     AND country = 'US' 
    ) AS 14d_rolling_users 
FROM p.action q 
WHERE dt BETWEEN '2016-08-24' AND '2016-10-24' 
GROUP BY dt 
ORDER BY dt ASC 

Я ломаю голову, пытаясь понять, как я мог бы сделать это без всего работает 60 индивидуальных запросов (по одному на каждый день).

Любая помощь приветствуется, спасибо!

ответ

1

Не имеют опыт работы с вуаля, но логически, вы можете переписать запрос, чтобы сделать декартово произведение присоединиться (присоединиться без каких-либо условий) в p.action с 2 месяца даты ограничений с p.action с той же датой 2 моли ограничений, то вам не нужен внутренний запрос.

SELECT dt,COUNT(DISTINCT user_id) 
FROM p.action q1,p.action q2 
WHERE q1.dt BETWEEN '2016-08-24' AND '2016-10-24' 
    AND q2.dt BETWEEN '2016-08-24' AND '2016-10-24' 
    AND q1.dt BETWEEN q2.dt - 13 AND q2.dt -- period of 14 days 
    AND country = 'US' 
GROUP BY q1.dt 
ORDER BY q1.dt ASC 

Было бы более эффективно создать таблицу за 2 месяца заранее - здесь условия применяются после объединения.

0

Начиная с версии 0.153 Presto содержит начальную поддержку коррелированных подзапросов. (См. https://prestodb.io/docs/current/release/release-0.153.html).

Ваш запрос должен пройти, если вы могли бы опустить DISTINCT

SELECT dt, 
    (SELECT COUNT(user_id) 
    FROM p.action 
    WHERE dt BETWEEN q.dt - 13 AND q.dt -- period of 14 days 
     AND country = 'US' 
    ) AS 14d_rolling_users 
FROM p.action q 
WHERE dt BETWEEN '2016-08-24' AND '2016-10-24' 
GROUP BY dt 
ORDER BY dt ASC 

Я знаю, что выше переписывание имеет совершенно другой семантический, чем ваш первоначальный запрос. Но я надеюсь, что это даст вам представление о том, что разрешено в Presto, поэтому вы можете переписать свой запрос так, как вам нравится.

В любом случае, я создал проблему для этого. Надеюсь, скоро он будет исправлен. См. https://github.com/prestodb/presto/issues/6480.

0

Лучший рулонный рулон.

Это превращает каждую строку в ваш стол в 14 строк с дополнительными отметками rollup__ds. Затем мы группируем этот новый столбец для создания календарного 14-дневного окна. Сложность этого - O(N*14) = O(N) и, следовательно, линейная.

SELECT 
    rollup__ds, 
    COUNT(DISTINCT username) 
FROM (
    SELECT 
    username, 
    ds 
    FROM 
    actions 
    WHERE 
    ds BETWEEN '2016-08-24' AND '2016-10-24' 
    AND country = 'US' 
) 
CROSS JOIN 
    UNNEST(ARRAY[ 
    DATE_ADD('day', 0, CAST(ds AS DATE)), 
    DATE_ADD('day', 1, CAST(ds AS DATE)), 
    ... 
    DATE_ADD('day', 12, CAST(ds AS DATE)), 
    DATE_ADD('day', 13, CAST(ds AS DATE)) 
    ]) AS t (rollup__ds) 
GROUP BY 
    rollup__ds 
ORDER BY 
    rollup__ds 
; 

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


если НБ вам не нужен четкий подсчет лучше использовать оконную функцию, увы это не работает для отдельного подсчета, потому что они не суммируют, как это.

SELECT 
    ds, 
    -- BEWARE this count is NOT distinct! 
    SUM(COUNT(username)) over (ORDER BY ds ROWS BEWTEEN 13 PRECEDING AND CURRENT ROW) 
FROM 
    actions 
WHERE 
    ds BETWEEN '2016-08-24' AND '2016-10-24' 
    AND country = 'US' 
;