如何引用 BigQuery SQL 中先前行的列值,以便执行操作或计算?

Posted

技术标签:

【中文标题】如何引用 BigQuery SQL 中先前行的列值,以便执行操作或计算?【英文标题】:How can I reference column values from previous rows in BigQuery SQL, in order to perform operations or calculations? 【发布时间】:2019-02-15 21:52:00 【问题描述】:

我已按开始时间对数据进行了排序,我想创建一个新字段来汇总与前几行开始时间和结束时间重叠的开始时间的数据。

更具体地说,我想编写逻辑,对于给定的记录 X,如果开始时间介于前一行的开始时间和结束时间之间,我想为记录 X 赋予与新字段相同的值前一行。如果开始时间在上一行的结束时间之后,它将为新字段获取一个新值。

在 BigQuery SQL 中是否可能出现这样的情况?正在考虑可能是滞后或窗口功能,但不太确定。下面是基本表的示例以及我想要的最终表的示例。

任何见解都值得赞赏!

【问题讨论】:

【参考方案1】:

以下是 BigQuery 标准 SQL

#standardSQL
SELECT recordID, startTime, endTime,
  COUNTIF(newRange) OVER(ORDER BY startTime) AS newRecordID
FROM (
  SELECT *, 
    startTime >= MAX(endTime) OVER(ORDER BY startTime ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING) AS newRange
  FROM `project.dataset.table`
)

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

#standardSQL
WITH `project.dataset.table` AS (
  SELECT 1 recordID, TIME '12:35:00' startTime, TIME '12:50:00' endTime UNION ALL
  SELECT 2, '12:46:00', '12:59:00' UNION ALL
  SELECT 3, '14:27:00', '16:05:00' UNION ALL
  SELECT 4, '15:48:00', '16:35:00' UNION ALL
  SELECT 5, '16:18:00', '17:04:00' 
)
SELECT recordID, startTime, endTime,
  COUNTIF(newRange) OVER(ORDER BY startTime) AS newRecordID
FROM (
  SELECT *, 
    startTime >= MAX(endTime) OVER(ORDER BY startTime ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING) AS newRange
  FROM `project.dataset.table`
)
-- ORDER BY startTime

结果

Row recordID    startTime   endTime     newRecordID  
1   1           12:35:00    12:50:00    0    
2   2           12:46:00    12:59:00    0    
3   3           14:27:00    16:05:00    1    
4   4           15:48:00    16:35:00    1    
5   5           16:18:00    17:04:00    1    

【讨论】:

很好的答案,米哈伊尔,很高兴地支持这个,它帮助解决了我的挑战【参考方案2】:

这是一个空白和孤岛问题。您想要做的是将组 ID 分配给不相交的组。您可以使用窗口函数计算非交叉点。

如果结束时间的累积最大值(按开始时间排序并在前一条记录结束)小于当前结束时间,则记录开始一个新组。其余的只是分配组 id 的累积总和。

对于您的数据:

select t.*,
       sum(case when prev_endtime >= endtime then 0 else 1 end) over (order by starttime) as group_id
from (select t.*,
             max(endtime) over (order by starttime rows between unbounded preceding and 1 preceding) as prev_endtime
      from t
     ) t;

唯一的潜在问题是两条记录是否同时开始。如果发生这种情况,逻辑可能需要稍微复杂一些。

【讨论】:

这太好了,谢谢。不应该有任何完全相同的开始时间戳,但我确实有不同的事件 ID - 您将如何更新语法以确保我们仅在它们遵循时间戳逻辑并且它们位于相同事件 ID 时才将它们聚集在一起.我在子查询中添加了一个“分区依据”,但效果不佳 @Andrew 。 . .您可以将partition by eventId 添加到窗口函数中。您的问题没有提及此类 ID。如果您不知道如何做到这一点,那么我建议您提出一个问题。

以上是关于如何引用 BigQuery SQL 中先前行的列值,以便执行操作或计算?的主要内容,如果未能解决你的问题,请参考以下文章

根据第三列值在 bigquery 中选择两个不同的列

有没有一种有效的方法来计算 Pandas 中的列值,使用基于其他列的条件值的前行的值?

更改 bigquery 中的列值

如何在 BigQuery 标准 SQL 中查询 Bigtable 列值?

BigQuery/SQL:如何使用列值作为列名? [复制]

如何在 SQL 中显示某一行的列值?