如何删除我的子选择中的相关子查询(由于presto限制)

x33g5p2x  于 2021-06-28  发布在  Hive
关注(0)|答案(2)|浏览(371)

我试图找出过去2个月内,在14天的滚动窗口内执行特定操作(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个单独的查询(每天一个)。
感谢您的帮助,谢谢!

khbbv19g

khbbv19g1#

我没有使用presto的经验,但从逻辑上讲,您可以重写查询来执行的笛卡尔乘积联接(join without no conditions) 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个月表会更有效—这里的条件是在连接之后应用的。

gtlvzcf8

gtlvzcf82#

最好是手动汇总。
这会将表中的每一行转换为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
;

希望有帮助!
注意:如果您不需要distinct count,那么最好使用窗口函数,唉,这对distinct count不起作用,因为它们不是那样可求和的。

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

相关问题