BigQuery:如何在滚动时间戳窗口内对行进行分组和计数?

Posted

技术标签:

【中文标题】BigQuery:如何在滚动时间戳窗口内对行进行分组和计数?【英文标题】:BigQuery: how to group and count rows within rolling timestamp window? 【发布时间】:2016-10-27 16:01:13 【问题描述】:

我有一些使用 MongoDB 的经验,并且正在学习 BigQuery。我正在尝试执行以下任务,但我不知道如何使用 BigQuery 的标准 SQL 来完成。

我有一张包含以下数据的表格。它包含在不同网站 url 上发生的事件。时间戳表示给定事件发生的时间。例如,第一行表示“事件 'xx' 在 2016 年 10 月 18 日 15:55:16 UTC 发生在 url 'a.html' 上。”

event_id |    url    |          timestamp   
-----------------------------------------------------------
   xx         a.html      2016-10-18 15:55:16 UTC
   xx         a.html      2016-10-19 16:68:55 UTC
   xx         a.html      2016-10-25 20:55:57 UTC
   yy         b.html      2016-10-18 15:58:09 UTC
   yy         a.html      2016-10-18 08:32:43 UTC
   zz         a.html      2016-10-20 04:44:22 UTC
   zz         c.html      2016-10-21 02:12:34 UTC

我想在滚动的 3 天窗口内计算每个网址上发生的每个事件的数量。换句话说,我希望能够说以下内容:

“在 url 'a.html' 上,在时间间隔 [2016-10-18 00:00:00 UTC,2016-10-21 00:00:00 UTC)期间,发生了事件 'xx'两次。”

“在 url 'a.html' 上,在时间间隔 [2016-10-19 00:00:00 UTC,2016-10-22 00:00:00 UTC)期间,发生了事件 'xx'一次。”

"在 url 'a.html' 上,在时间间隔 [2016-10-20 00:00:00 UTC,2016-10-23 00:00:00 UTC),事件 'xx' 发生零次。” (注意:这不需要作为一行返回。没有这一行可能意味着该事件发生了零次。)

一些注意事项:我的数据库每天包含超过 10 万行,并且事件的发生情况各不相同。这意味着,在 1 天内,事件“xx”将发生约 10,000 次,事件“zz”将发生约 0-2 次。

鉴于我有限的 SQL 知识,我不想为结果表提供结构,因为我认为这可能会错误地限制可能的答案。谢谢!

【问题讨论】:

查看***.com/a/49866033/132438 以获取具有近似结果的更快解决方案 - 以防您还需要滚动计数唯一性。 【参考方案1】:

以下是 BigQuery 标准 SQL(请参阅 Enabling Standard SQL

我使用ts 作为字段名称(而不是您的示例中的timestamp)并假设该字段是TIMESTAMP 数据类型

WITH dailyAggregations AS (
  SELECT 
    DATE(ts) AS day, 
    url, 
    event_id, 
    UNIX_SECONDS(TIMESTAMP(DATE(ts))) AS sec, 
    COUNT(1) AS events 
  FROM yourTable
  GROUP BY day, url, event_id, sec
)
SELECT 
  url, event_id, day, events, 
  SUM(events) 
    OVER(PARTITION BY url, event_id ORDER BY sec 
      RANGE BETWEEN 259200 PRECEDING AND CURRENT ROW
  ) AS rolling3daysEvents
FROM dailyAggregations
-- ORDER BY url, event_id, day

259200 的值实际上是 3x24x3600 所以设置 3 天的范围,所以你可以设置任何你需要的实际滚动周期

【讨论】:

这行得通,让我看看我是否完全理解它:1)创建一个按天对事件进行分组和计数的中间表。它还将时间戳字段转换为其等效的 unix 秒。 2) 使用以秒为单位的窗口总结事件? 当然,如果需要请询问 还有几个问题:1) 是否可以在没有中间每日聚合的情况下执行此操作? (即:假设我们希望窗口为 10 分钟而不是 3 天)。 2) 是否可以修改查询,使一天的概念与特定时区有关,而不仅仅是 UTC? (我们能否以某种方式将 AT TIME ZONE "America/New_York" 与 DATE(ts) 一起使用?)再次感谢...我是 BigQuery 和 SQL 的菜鸟。 另外,这段代码很好用。需要注意的是,它提供了一个 4 天的窗口,我可以轻松地将其调整为 3 天。 1) 当然 - 每日汇总是有意义的,因为最初的问题是如何制定的(3 个滚动 DAYS)。所以很容易修改N分钟。让我知道您是否想要示例,否则您将自己尝试。 2) 轻松 - 见cloud.google.com/bigquery/sql-reference/data-types#time-zones

以上是关于BigQuery:如何在滚动时间戳窗口内对行进行分组和计数?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Python 在一个时间段内对行进行分组

您能否创建一个 BigQuery UDF 来生成表列表,而不是对行进行操作?

当您的数据不在偶数时间间隔内时,是不是有一种快速方法可以在偶数时间间隔内对 Pandas Dataframe 进行滚动求和?

使用 SQL,我怎样才能在给定的天数内对每一天的未指定数量的记录进行滚动平均?

如何对 BigQuery 表进行分片?

FineReport报表开发工具中,如何对行进行强制分页,但是列全部显示?