BigQuery:如何执行滚动时间戳窗口组计数,每天产生行

Posted

技术标签:

【中文标题】BigQuery:如何执行滚动时间戳窗口组计数,每天产生行【英文标题】:BigQuery: how to perform rolling timestamp window group count that produces row for each day 【发布时间】:2016-11-07 23:53:42 【问题描述】:

这是我在 *** here 上提出并解决的问题的扩展。

我是 BigQuery 和 SQL 新手,我想构建一个标准 SQL 查询,该查询将在 X 天的滚动时间窗口内对事件进行分组和计数。我的数据表如下所示:

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

我正在跟踪 url 上发生的事件。我想知道在 X 天的滚动时间段内每个事件在每个 url 上发生了多少次。当我问这个问题时,我得到了一个很好的答案:

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 rolling4daysEvents
FROM dailyAggregations

其中 259200 是以秒为单位的 3 天 (3x24x3600)。据我了解,此查询创建了一个按天对事件进行分组和计数的中间表。它还将时间戳字段转换为其等效的 unix 秒。然后它使用以秒为单位的窗口总结事件。

现在这将生成一个包含正确运行总计的表格,但它不能保证每个日期、url 和事件都有一行。换句话说,如果给定 url 上从未发生给定事件的日期,则结果表中将缺少日期。底线,我可以修改上述查询(或构造一个不同的查询),以正确地为间隔中的每个日期生成 rolling4daysEvents 的值吗? eg:就像一个区间定义为:

SELECT *
  FROM UNNEST (GENERATE_DATE_ARRAY('2016-08-28', '2016-11-06')) AS day
  ORDER BY day ASC

谢谢!

【问题讨论】:

【参考方案1】:
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
),
calendar AS (
  SELECT day
  FROM UNNEST (GENERATE_DATE_ARRAY('2016-08-28', '2016-11-06')) AS day
)
SELECT 
  c.day, url, event_id, events, 
  SUM(events) 
    OVER(PARTITION BY url, event_id ORDER BY sec 
      RANGE BETWEEN 259200 PRECEDING AND CURRENT ROW
  ) AS rolling4daysEvents
FROM calendar AS c
LEFT JOIN dailyAggregations AS a
ON a.day = c.day

【讨论】:

为了测试这个查询并查看单个案例,我在 dailyAggregations 查询中添加了一个“WHERE event_id = "xx" AND url="a.html"(就在 FROM yourTable 之后)。我获得了一个包含每个日期的行的表,但是没有事件发生的行对除“day”之外的所有列产生 NULL 值。 我明白了,您希望结果不仅是丢失的日子,而且在所有这些日子里,所有 url 和事件的组合?这是正确的吗? 正确,我希望为 date、event_id 和 url 的每个组合生成一个正确的 rolling4daysEvents 值——而不仅仅是事件发生的日期。如果执行此查询不切实际,我可以考虑编写代码(非 sql)以在查询后填写缺失的信息。 老实说,我认为这没有多大意义!你应该想想为什么你真的需要它并在那里修复一些东西。物理上产生所有可能的排列不是正确的方式!可行,但走错路 与此同时,您的问题非常明确地集中在您缺少日期的问题以及您处理 LEFT JOIN 的问题上 - 所以这部分已得到解决,希望对您有所帮助! :o)

以上是关于BigQuery:如何执行滚动时间戳窗口组计数,每天产生行的主要内容,如果未能解决你的问题,请参考以下文章

如何在滚动窗口上“检查”(警告)InfluxDB 2.0 中的聚合?

BigQuery 每 x 行返回数据

BigQuery SQL:滚动计数在两个条件之间有界

滚动计数器 24 小时时间戳 - pyspark

如何使用多索引对时间序列进行滚动窗口计数?

时间段之间的 BigQuery 计数实例分组依据