【问题标题】:how to get last 7 activities per user如何获取每个用户的最后 7 个活动
【发布时间】:2018-11-30 13:43:17
【问题描述】:

有人可以帮我解答一些问题吗?

所以我试图查看用户在本月的行为。我试图通过用户 ID 对他们的所有数据进行排序,但 bigquery 说:

查询执行期间资源超出:无法在分配的内存中执行查询。峰值使用量:限制的 107%。最高内存消耗者:ORDER BY 操作:100%。

因此,我想只获取用户的最后 10 个活动。 例如我有:

UserID        timestamp
123           28-Nov-2018
123           28-Nov-2018
123           28-Nov-2018
123           28-Nov-2018
123           27-Nov-2018
123           26-Nov-2018
123           20-Nov-2018
123           08-Nov-2018
123           08-Nov-2018
123           07-Nov-2018
123           05-Nov-2018
123           03-Nov-2018
234           28-Nov-2018
234           26-Nov-2018
234           25-Nov-2018
234           24-Nov-2018
234           24-Nov-2018

因此结果将是:

 UserID        timestamp
 123           28-Nov-2018
 123           28-Nov-2018
 123           28-Nov-2018
 123           28-Nov-2018
 123           27-Nov-2018
 123           26-Nov-2018
 123           20-Nov-2018
 123           08-Nov-2018
 123           08-Nov-2018
 123           07-Nov-2018
 234           28-Nov-2018
 234           26-Nov-2018
 234           25-Nov-2018
 234           24-Nov-2018
 234           24-Nov-2018

我应该只获取用户 123 的最后 10 个活动,同时捕获用户 234 的所有活动,因为它的活动小于 10

【问题讨论】:

  • 请出示您的查询。

标签: sql google-bigquery


【解决方案1】:

每位用户的最后 7 个活动

下面是 BigQuery 标准 SQL,应该解决通常与使用 ROW_NUMBER() 或 RANK() 和 ORDER BY 类型的函数相关的资源超出错误

注意:根据您的示例,我假设您的时间戳列的数据类型实际上是 STRING,所以我使用 PARSE_DATE() 函数将其转换为 DATE 类型

#standardSQL
SELECT UserID, ts FROM (
  SELECT UserID, ARRAY_AGG(ts ORDER BY PARSE_DATE('%d-%b-%Y', ts) DESC LIMIT 7) arr
  FROM `project.dataset.table`
  GROUP BY UserID
), UNNEST(arr) ts

您可以像在您的问题中那样使用虚拟数据进行测试和使用:

#standardSQL
WITH `project.dataset.table` AS (
  SELECT 123 UserID, '28-Nov-2018' ts UNION ALL
  SELECT 123, '28-Nov-2018' UNION ALL
  SELECT 123, '28-Nov-2018' UNION ALL
  SELECT 123, '28-Nov-2018' UNION ALL
  SELECT 123, '27-Nov-2018' UNION ALL
  SELECT 123, '26-Nov-2018' UNION ALL
  SELECT 123, '20-Nov-2018' UNION ALL
  SELECT 123, '08-Nov-2018' UNION ALL
  SELECT 123, '08-Nov-2018' UNION ALL
  SELECT 123, '07-Nov-2018' UNION ALL
  SELECT 123, '05-Nov-2018' UNION ALL
  SELECT 123, '03-Nov-2018' UNION ALL
  SELECT 234, '28-Nov-2018' UNION ALL
  SELECT 234, '26-Nov-2018' UNION ALL
  SELECT 234, '25-Nov-2018' UNION ALL
  SELECT 234, '24-Nov-2018' UNION ALL
  SELECT 234, '24-Nov-2018' 
)
SELECT UserID, ts FROM (
  SELECT UserID, ARRAY_AGG(ts ORDER BY PARSE_DATE('%d-%b-%Y', ts) DESC LIMIT 7) arr
  FROM `project.dataset.table`
  GROUP BY UserID
), UNNEST(arr) ts
ORDER BY UserID, PARSE_DATE('%d-%b-%Y', ts) DESC   

结果

Row UserID  ts   
1   123     28-Nov-2018  
2   123     28-Nov-2018  
3   123     28-Nov-2018  
4   123     28-Nov-2018  
5   123     27-Nov-2018  
6   123     26-Nov-2018  
7   123     20-Nov-2018  
8   234     28-Nov-2018  
9   234     26-Nov-2018  
10  234     25-Nov-2018  
11  234     24-Nov-2018  
12  234     24-Nov-2018  

【讨论】:

    【解决方案2】:

    这确实可行:

            create table d061_userid (userid number,tt date);
            //do inserts 
            select * from d061_userid;
    123 28-NOV-18
    123 28-NOV-18
    123 28-NOV-18
    123 28-NOV-18
    123 27-NOV-18
    123 20-NOV-18
    123 08-NOV-18
    123 08-NOV-18
    123 07-NOV-18
    123 05-NOV-18
    123 03-NOV-18
    234 28-NOV-18
    234 26-NOV-18
    234 25-NOV-18
    234 24-NOV-18
    
      select a.userID,a.tt from (select userID, tt,
      row_number() over (partition by userID order by tt desc) rank
      from d061_userid
      ) a where rank<=7 ;
    
    
        output:
    123 28-NOV-18
    123 28-NOV-18
    123 28-NOV-18
    123 28-NOV-18
    123 27-NOV-18
    123 20-NOV-18
    123 08-NOV-18
    234 28-NOV-18
    234 26-NOV-18
    234 25-NOV-18
    234 24-NOV-18
    234 24-NOV-18
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-01-05
      • 1970-01-01
      • 1970-01-01
      • 2022-10-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多