如何删除我的子选择中的相关子查询(由于 presto 限制)
How to remove correlated subquery in my subselect (due to presto limitation)
我正在尝试查找在过去 ~2 的 14 天滚动 window 内执行特定操作(p.action 中的任何行)的美国用户的不同数量个月。
这是查询。我喜欢一些关于如何重写它以不使用相关子查询的提示,因为 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 个单独的查询(每天一个)的情况下完成此操作。
感谢任何帮助,谢谢!
没有使用 presto 的经验,但从逻辑上讲,您可以重写查询以执行 p.action
的笛卡尔乘积连接(无条件连接),日期限制为 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 个月 table 会更有效率 - 这里的条件是在加入后应用的。
最好手动汇总。
这会将 table 中的每一行变成 14 行,并带有额外的 rollup__ds
时间戳。然后我们按这个新列分组以创建滚动的 14 天 window。它的复杂性是 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
;
希望对您有所帮助!
注意—如果您不需要非重复计数最好使用 window 函数,唉,这对非重复计数不起作用,因为它们不能像那样求和。
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'
;
我正在尝试查找在过去 ~2 的 14 天滚动 window 内执行特定操作(p.action 中的任何行)的美国用户的不同数量个月。
这是查询。我喜欢一些关于如何重写它以不使用相关子查询的提示,因为 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 个单独的查询(每天一个)的情况下完成此操作。
感谢任何帮助,谢谢!
没有使用 presto 的经验,但从逻辑上讲,您可以重写查询以执行 p.action
的笛卡尔乘积连接(无条件连接),日期限制为 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 个月 table 会更有效率 - 这里的条件是在加入后应用的。
最好手动汇总。
这会将 table 中的每一行变成 14 行,并带有额外的 rollup__ds
时间戳。然后我们按这个新列分组以创建滚动的 14 天 window。它的复杂性是 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
;
希望对您有所帮助!
注意—如果您不需要非重复计数最好使用 window 函数,唉,这对非重复计数不起作用,因为它们不能像那样求和。
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'
;