【问题标题】:See all usage for the last 30 days, grouped by user and rolling查看过去 30 天的所有使用情况,按用户和滚动分组
【发布时间】:2018-07-18 21:39:24
【问题描述】:

我有一个文件,其中记录了我们产品的所有使用情况,其中包括用户 ID、拨打电话的次数和拨打电话的日期(按用户 ID 汇总到日期)。

user_id |电话号码 |日期

123 | 32 | 2018-04-17

435 | 21 | 2018-04-17

123 | 35 | 2018-04-18

435 | 10 | 2018-04-18

123 | 20 | 2018-04-19

435 | 90 | 2018-04-20

我想制作一个图表,显示过去和以后每一天的用户,在该日期之前(包括该日期)的 30 天内活跃的用户,以及他们在该 30 天内拨打的电话次数。最终,我将使用它在给定的 30 天内为“高使用率”设置各种阈值。它看起来像这样:

user_id | num_calls_in_previous_30_days |日期

123 | 32 | 2018-04-17

435 | 21 | 2018-04-17

123 | 67 | 2018-04-18

435 | 31 | 2018-04-18

123 | 87 | 2018-04-19

435 | 31 | 2018-04-19

123 | 87 | 2018-04-20

435 | 121 | 2018-04-20

我遇到的问题是当我尝试使用窗口功能时

sum(num_calls) over (partition by id ORDER BY UNIX_SECONDS(timestamp(date)) range BETWEEN 2505600 PRECEDING AND CURRENT ROW)

我只获取在每个特定日期活跃的用户在过去 30 天内的通话总数,而不是包括在该日期之前 30 天内活跃的所有用户及其在该时间范围内的使用情况。使用上面的相同数据,它看起来像这样:

user_id | num_calls_in_previous_30_days |日期

123 | 32 | 2018-04-17

435 | 21 | 2018-04-17

123 | 67 | 2018-04-18

435 | 31 | 2018-04-18

123 | 87 | 2018-04-19

435 | 121 | 2018-04-20

我尝试了另一条路线,该路线从每个日期开始获取前 30 天的所有唯一 user_id,但我不知道如何将其与我现有的使用数据相结合以获得我想要的结果。

我确信这里有一个简单的解决方案,但我已经花了几个小时来解决这个问题。

提前致谢!

【问题讨论】:

    标签: sql google-bigquery


    【解决方案1】:

    以下示例适用于 BigQuery 标准 SQL

    #standardSQL
    WITH dates AS (
      SELECT DATE
      FROM (
        SELECT MIN(DATE) start, MAX(DATE) finish
        FROM `project.dataset.table`
      ), UNNEST(GENERATE_DATE_ARRAY(start, finish)) DATE
    ), users AS (
      SELECT DISTINCT user_id 
      FROM `project.dataset.table`
    )
    SELECT user_id, num_calls, DATE,
      SUM(num_calls) OVER (win30days) num_calls_in_previous_30_days
    FROM users
    CROSS JOIN dates
    LEFT JOIN `project.dataset.table` USING(DATE, user_id)
    WINDOW win30days AS (
      PARTITION BY user_id 
      ORDER BY UNIX_SECONDS(TIMESTAMP(DATE)) 
      RANGE BETWEEN 2505600 PRECEDING AND CURRENT ROW
    )
    

    您可以使用您问题中的虚拟数据进行测试,如下所示

    #standardSQL
    WITH `project.dataset.table` AS (
      SELECT 123 user_id, 32 num_calls, DATE '2018-04-17' DATE UNION ALL
      SELECT 435, 21, '2018-04-17' UNION ALL
      SELECT 123, 35, '2018-04-18' UNION ALL
      SELECT 435, 10, '2018-04-18' UNION ALL
      SELECT 123, 20, '2018-04-19' UNION ALL
      SELECT 435, 90, '2018-04-20' 
    ), dates AS (
      SELECT DATE
      FROM (
        SELECT MIN(DATE) start, MAX(DATE) finish
        FROM `project.dataset.table`
      ), UNNEST(GENERATE_DATE_ARRAY(start, finish)) DATE
    ), users AS (
      SELECT DISTINCT user_id 
      FROM `project.dataset.table`
    )
    SELECT user_id, num_calls, DATE,
      SUM(num_calls) OVER (win30days) num_calls_in_previous_30_days
    FROM users
    CROSS JOIN dates
    LEFT JOIN `project.dataset.table` USING(DATE, user_id)
    WINDOW win30days AS (
      PARTITION BY user_id 
      ORDER BY UNIX_SECONDS(TIMESTAMP(DATE)) 
      RANGE BETWEEN 2505600 PRECEDING AND CURRENT ROW
    )
    -- ORDER BY DATE, user_id
    

    结果为

    Row user_id num_calls   DATE            num_calls_in_previous_30_days    
    1   123     32          2018-04-17      32   
    2   435     21          2018-04-17      21   
    3   123     35          2018-04-18      67   
    4   435     10          2018-04-18      31   
    5   123     20          2018-04-19      87   
    6   435     null        2018-04-19      31   
    7   123     null        2018-04-20      87   
    8   435     90          2018-04-20      121  
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-27
      • 2018-08-26
      • 2011-08-24
      • 2013-07-08
      • 2023-01-15
      • 2020-10-18
      • 1970-01-01
      • 2020-05-12
      相关资源
      最近更新 更多