大查询SQL:确定满足条件的最小长度的时间范围

大查询SQL:确定满足条件的最小长度的时间范围,sql,google-bigquery,Sql,Google Bigquery,我的问题的一个简化版本是,我有一个包含以下字段的表:id、timestamp和numeric variable speed。我需要确定时间段开始和结束时间戳,其中速度的平均值小于阈值(比如2),但时间段结束时间戳-开始时间戳至少是最小持续时间(比如5小时或更长)。基本上,我需要计算初始5小时窗口的平均值,如果平均值小于阈值,则保留开始时间戳,并使用结束时间戳向前移动一行,然后重新计算平均值。如果新平均值小于阈值,则再次向前保持一步,扩展时间窗口。如果新的平均值大于阈值,则报告前一个end_时间戳

我的问题的一个简化版本是,我有一个包含以下字段的表:id、timestamp和numeric variable speed。我需要确定时间段开始和结束时间戳,其中速度的平均值小于阈值(比如2),但时间段结束时间戳-开始时间戳至少是最小持续时间(比如5小时或更长)。基本上,我需要计算初始5小时窗口的平均值,如果平均值小于阈值,则保留开始时间戳,并使用结束时间戳向前移动一行,然后重新计算平均值。如果新平均值小于阈值,则再次向前保持一步,扩展时间窗口。如果新的平均值大于阈值,则报告前一个end_时间戳作为此窗口的end_时间戳,并启动一个新的start_时间戳,并计算未来5小时的新平均值。最终,最终产品是一个表,具有一组开始时间戳、结束时间戳和计算的持续时间,平均速度小于2,开始和结束之间的时间至少为5小时

我正在使用谷歌大查询: 这是我到目前为止的总体结构,但它似乎并没有按照我所希望的方式工作。首先,它只测试并报告初始5小时窗口的速度阈值…即使窗口增长。其次,它似乎没有适当地扩大窗口。窗口很少超过5小时,尽管在某些情况下查看我的数据时,窗口的长度应该是5小时的两倍。我希望有人已经尝试开发出类似的分析,并能阐明我的错误所在

SELECT
*,
LEAD(start_timestamp) OVER (PARTITION BY id ORDER BY timestamp) AS
next_start_timestamp,
LEAD(end_timestamp) OVER (PARTITION BY id ORDER BY timestamp) AS
next_end_timestamp
FROM (
SELECT
*,
IF(last_timestamp IS NULL
  OR timestamp - last_timestamp > 1000000*60*60*5, TRUE, FALSE) AS start_timestamp, #1000000*60*60*5 = 5 hours in microseconds
IF(next_timestamp IS NULL
  OR next_timestamp - timestamp > 1000000*60*60*5, TRUE, FALSE) AS end_timestamp #1000000*60*60*5 = 5 hours in microseconds
FROM (
SELECT
  *,
  LAG(timestamp,1) OVER (PARTITION BY id ORDER BY timestamp) last_timestamp,
  LEAD(timestamp,1) OVER (PARTITION BY id ORDER BY timestamp) next_timestamp,
FROM (
  SELECT
    *,
    AVG(speed) OVER (PARTITION BY id ORDER BY timestamp RANGE BETWEEN 5 * 60 * 60 * 1000000 PRECEDING AND CURRENT ROW) AS avg_speed_last_period,
  FROM (
      SELECT
        id,
        timestamp,
        speed
      FROM
        [dataset.table1]))
WHERE
  avg_speed_last_period < 2
ORDER BY
  id,
  timestamp)
HAVING
  start_timestamp
  OR end_timestamp)

根据您的CSV,我假设以下模式

其中包含以下数据:

记住这一点-下面是BigQuery标准SQL的工作代码 输出完全符合您的期望

 id                 start_event                 end_event   average_speed   duration_hrs
203     2015-01-08 17:40:00 UTC   2015-01-09 07:09:00 UTC            0.78          13.48  
203     2015-01-10 03:43:00 UTC   2015-01-10 08:48:00 UTC            1.45           5.08  
标准SQL 创建临时函数identificationtimeranges 项目数组, 最小长度INT64,阈值浮点64,最大速度浮点64 返回数组 语言JSAS var结果=[]; var初始值=0; var候选者=项目[初始].ts; var-len=0; var总和=0; 对于i=0;i最大速度{ 初始值=i+1; 候选项=项目[初始].ts; len=0; 总和=0; } 持续 } 如果总和/长度>阈值| |项[i]。速度>最大速度{ 平均速度=总和项目[i]。速度/长度-1; 如果平均速度=最小长度{ var o=[]; o、 start\u event=items[initial].datetime; o、 平均转速=平均转速.toFixed3; o、 end_event=items[i-1]。日期时间; o、 持续时间=项目[i-1].ts-items[初始值].ts/60/60.toFixed3 普索结果 } 初始=i; 候选项=项目[初始].ts; len=1; 总和=项目[初始]。速度; } }; 返回结果; ; 以数据为基础 选择id,分析时间戳“%m/%d/%y%H:%m”,日期时间为日期时间,速度 从你的桌子上` ,压缩数据为 选择id、数组、UNIX\u SECONDSdatetime、速度、日期时间顺序(按UNIX\u SECONDSdatetime排序)作为点 从数据 按id分组 选择 id、开始事件、结束事件、平均速度、持续时间 从compact_数据中,取消将IdentificationTimeRangeSPoints、5*60*60、2、3.1作为段 按id订购,启动\u事件 请注意:此代码正在使用,这意味着一些,对于您来说,这取决于数据的大小

还请记住-如果datetime字段的数据类型不是字符串-您只需要稍微调整数据子查询-其余的应该保持原样

例如,如果datetime是时间戳数据类型,则只需替换

选择id,分析时间戳“%m/%d/%y%H:%m”,日期时间为日期时间,速度 从你的桌子上` 与

选择id、日期时间、速度 从你的桌子上`
希望您喜欢:o

示例数据和期望的结果将真正帮助解释。谢谢…添加了示例数据和示例输出您仍然给我们留下了一些漏洞-请在预期输出中添加第二行-至少对我来说,它将关闭一些我已使用第二行输出更新了帖子并更新了数据文件。我希望这有助于思考这个问题。@NateMiller-请澄清-datetime的数据类型是什么?从你的csv它是不清楚的!是时间戳还是字符串?
 id                 start_event                 end_event   average_speed   duration_hrs
203     2015-01-08 17:40:00 UTC   2015-01-09 07:09:00 UTC            0.78          13.48  
203     2015-01-10 03:43:00 UTC   2015-01-10 08:48:00 UTC            1.45           5.08