SQL(雪花)– 30天前瞻性/滚动平均值

时间:2020-08-12 12:50:53

标签: sql snowflake-cloud-data-platform

我有两个表– purchasesactivity

purchase表的结构如下:

|----------|----------------|----------|
|  user_id |  purchase_date |  status  |
|----------|----------------|----------|
|    1234  |   2020-01-01   |  active  |
|----------|----------------|----------|
|    2345  |   2020-01-10   | cancelled|

activity表的结构如下:

|----------|----------------|-----------------|
|  user_id |      date      |  videos_viewed  |
|----------|----------------|-----------------|
|    1234  |   2020-01-02   |       4         |
|----------|----------------|-----------------|
|    2345  |   2020-01-03   |       3         |
|----------|----------------|-----------------|
|    2345  |   2020-01-10   |       10        |
|----------|----------------|-----------------|
|    2345  |   2020-01-11   |       7         |

我希望根据设定的购买期限为每个用户的前30天查询前30天的活动平均值

到目前为止我写的查询是这样的:

SELECT avg(t3.viewsperday)
FROM
 (SELECT 
    date
   ,sum(t1.videos_viewed)/count(t1.user_id) as viewsperday
   FROM activity t1 
       INNER JOIN (SELECT * FROM purchase c
       WHERE status = 'active'
       AND purchase_date BETWEEN '2020-01-01' and '2020-02-01') t2 
   ON t1.user_id = t2.user_id
   where date between '2020-01-01' and '2020-02-01'
   group by 1
   order by 1 asc) as t3;

但是,这里的问题是,如果用户在2020-01-31上购物,那么我只会得到第一天的活动。我需要帮助来弄清楚如何获得滚动平均值/从每个购买日期起30天前-以及从这30天中获取平均活动。

我怀疑此处适合使用窗口函数,但是由于它有点超出我的知识范围,因此我不确定如何编写它。任何帮助将不胜感激。

1 个答案:

答案 0 :(得分:1)

以下应能工作。我假设即使在某些日子里的观看次数为零,您也希望获得30天以上的平均值?您可能还需要根据确切地定义30天日期范围的方式(即包含30天,包含购买日期等)进行稍微调整。 我将其写为外部联接,这样即使没有视图的用户也将被包括在内

SELECT
P.USER_ID,
SUM(A.VIDEOS_VIEWED)/30
FROM PURCHASE P
LEFT OUTER JOIN ACTIVITY A ON P.USER_ID = A.USER_ID AND
A.DATE >= P.PURCHASE_DATE AND A.DATE <= dateadd(DAY, 30, P.PURCHASE_DATE)
GROUP BY P.USER_ID;

更新... 要获取每日平均值,请尝试以下操作(购买日期的视图显示为第0天,如果应将第1天设为1,则将其添加到Day_after_Purchase公式中):

SELECT
(a.date - p.purchase_date) as Day_after_Purchase,
avg(A.VIDEOS_VIEWED)
FROM PURCHASE P
LEFT OUTER JOIN ACTIVITY A ON P.USER_ID = A.USER_ID AND
    A.DATE >= P.PURCHASE_DATE AND A.DATE <= dateadd(DAY, 30, P.PURCHASE_DATE)
GROUP BY 1;