2016-10-28 8 views
2

我試圖從14天的滾動窗口內執行特定操作(p.action中的任何行)的美國用戶的不同計數,過去〜2個月。如何刪除我的子查詢中的相關子查詢(由於presto限制)

以下是查詢。我很想知道如何將這個重寫爲不使用相關子查詢的一些技巧,因爲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 
; 

希望有幫助!


NB-如果你不需要重複計數最好使用窗口功能,可惜這並不適用於不同的計數工作,因爲他們不累加這樣。

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' 
;