【问题标题】:BigQuery: Computing aggregate over window of time for each personBigQuery:计算每个人在时间窗口内的聚合
【发布时间】:2015-12-26 17:41:58
【问题描述】:

给定 Google BigQuery 中的一个表:

User  Timestamp 
A     TIMESTAMP(12/05/2015 12:05:01.8023)
B     TIMESTAMP(9/29/2015 12:15:01.0323)
B     TIMESTAMP(9/29/2015 13:05:01.0233)
A     TIMESTAMP(9/29/2015 14:05:01.0432)
C     TIMESTAMP(8/15/2015 5:05:01.0000)
B     TIMESTAMP(9/29/2015 14:06:01.0233)
A     TIMESTAMP(9/29/2015 14:06:01.0432)

有没有简单的计算方法:

User  Maximum_Number_of_Events_this_User_Had_in_One_Hour  
A     2
B     3
C     1

一小时的时间窗口在哪里是一个参数?

我尝试自己使用 LAG 和分区函数的组合来解决这两个问题:

BigQuery SQL for 28-day sliding window aggregate (without writing 28 lines of SQL)

Bigquery SQL for sliding window aggregate

但是发现这些帖子太不相似了,因为我不是在查找每个时间窗口的人数,而是在一个时间窗口内查找每个人的最大事件数。

【问题讨论】:

  • 顺便说一句:用户 B 的预期值“3”是错误的 - 应该是 2!因为 1:05、1:06 和 12:15 之间的距离远远超过 1 小时。除非以某种方式涉及地点
  • 谢谢!修正了这个例子:)

标签: sql aggregate-functions google-bigquery window-functions


【解决方案1】:

这是一种利用时间戳的有序结构的高效简洁方法。

SELECT
  user,
  MAX(per_hour) AS max_event_per_hour
FROM
(
  SELECT 
    user,
    COUNT(*) OVER (PARTITION BY user ORDER BY timestamp RANGE BETWEEN 60 * 60 * 1000000 PRECEDING AND CURRENT ROW) as per_hour,
    timestamp
  FROM 
    [dataset_example_in_question_user_timestamps]
)
GROUP BY user

【讨论】:

  • RANGE 的大量使用。不过,您仍然需要获得 MAX。还有一个 - 您的示例表中的时间戳是刺痛的,因此您需要将其转换为时间戳,然后转换为 sec 或 msec 才能使上述工作。还是很不错的!
【解决方案2】:

试试下面的 GBQ。没有测试太多,但对我来说看起来可行

SELECT
  User, Max(events) as Max_Events
FROM (
  SELECT 
    b.User as User, 
    b.Timestamp as Timestamp,
    COUNT(1) as Events
  FROM [your_dataset.your_table] as b
  JOIN (
    SELECT User, Timestamp 
    FROM [your_dataset.your_table]
    ) as w 
  ON w.User = b.User
  WHERE ROUND((TIMESTAMP_TO_SEC(TIMESTAMP(w.Timestamp)) - 
               TIMESTAMP_TO_SEC(TIMESTAMP(b.Timestamp))) / 3600, 1) BETWEEN 0 AND 1
  GROUP BY 1, 2
)
GROUP BY 1

【讨论】:

  • 感谢您的回答 - 但我想出了一个更好的答案,所以我将发布它。在我接受我自己的答案之前,我会让你看看 - 看看你的想法!
【解决方案3】:

我认为您可以使用这样的查询(在 T-SQL 中):

SELECT "User", SUM(s) As Maximum_Number_of_Events_this_User_Had_in_One_Hour  
FROM (
    SELECT "User", 1 s
    FROM yourTable
    GROUP BY "User", CAST("Timestamp" As date), DATEPART(Hour, "Timestamp")) As t
GROUP BY "User"

【讨论】:

  • 他提到他使用 Google BigQuery。
  • 感谢您的回答 - 但我想出了一个更好的答案,所以我将发布它。在我接受我自己的答案之前,我会让你看看 - 看看你的想法!
猜你喜欢
  • 2018-06-14
  • 1970-01-01
  • 2020-06-28
  • 2023-01-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-08-15
  • 1970-01-01
相关资源
最近更新 更多