仅使用时间戳识别数据中的数据空白

时间:2019-03-27 01:58:48

标签: sql google-bigquery timestamp

我正在尝试查询一个针对Google BigQuery数据的查询,这将使我能够识别差距所在的位置,即只有时间戳(即没有开始日期和结束日期)的数据,按该时间戳排序,并且行上有非连续的ID号。

Sample data:

Row     localised_sample_date_time  
1       2019-03-21T00:00:29
2       2019-03-21T00:01:29
3       2019-03-21T00:02:29
4       2019-03-21T00:04:29
3       2019-03-21T00:05:29

每行数据都包含一个时间戳,并且每行数据都将以可预测的时间间隔(例如10分钟)出现。我正在寻找一个查询来说明哪里存在数据缺口,即何时不存在预期的“ 10分钟”行。

我希望数据看起来像这样:

data island
-------------------------------------------------------
[start timestamp of island] - [end timestamp of island]

例如

data island
-------------------------------------------------------
2019-03-21T00:00:29 - 2019-03-21T00:02:29
2019-03-21T00:04:29 - 2019-03-21T00:05:29

逻辑上,我正在寻找类似的东西:

  • 按时间戳排序
  • 弄清楚连续记录之间是否有10分钟的间隔
  • 如果没有,则输出代表数据岛的开始和结束时间戳记。

这是一个很好的常规资源,它解释了如何识别数据间隙和孤岛-http://www.kodyaz.com/t-sql/data-islands-and-data-gaps-with-boundaries-using-sql.aspx-它似乎并未涵盖以我的方式构造的数据。

我认为必须使用可以对DATEADD,ORDER BY和GROUP BY进行某些操作的东西,以识别符合预期的10分钟间隔的记录组,但是我不知道如何我需要实现我想要实现的目标。什么是优雅,简单的解决方案?

1 个答案:

答案 0 :(得分:2)

以下是用于BigQuery标准SQL

#standardSQL
SELECT CONCAT(
    FORMAT_TIMESTAMP('%F %T', MIN(IF(gap, ts, previous_ts))), ' - ', FORMAT_TIMESTAMP('%F %T', MAX(ts))
  ) data_island
FROM (
  SELECT ts, previous_ts, gap, COUNTIF(gap) OVER(ORDER BY ts) grp
  FROM (
    SELECT ts, LAG(ts) OVER(ORDER BY ts) previous_ts,
      IFNULL(TIMESTAMP_DIFF(ts, LAG(ts, 1) OVER(ORDER BY ts), MINUTE), 2) > 1 gap
    FROM `project.dataset.table` 
  )
)
GROUP BY grp

您可以使用问题中的示例数据来测试,玩游戏,如下例所示

#standardSQL
WITH `project.dataset.table` AS (
  SELECT TIMESTAMP '2019-03-21T00:00:29' ts UNION ALL
  SELECT '2019-03-21T00:01:29' UNION ALL
  SELECT '2019-03-21T00:02:29' UNION ALL
  SELECT '2019-03-21T00:04:29' UNION ALL
  SELECT '2019-03-21T00:05:29' 
)
SELECT CONCAT(
    FORMAT_TIMESTAMP('%F %T', MIN(IF(gap, ts, previous_ts))), ' - ', FORMAT_TIMESTAMP('%F %T', MAX(ts))
  ) data_island
FROM (
  SELECT ts, previous_ts, gap, COUNTIF(gap) OVER(ORDER BY ts) grp
  FROM (
    SELECT ts, LAG(ts) OVER(ORDER BY ts) previous_ts,
      IFNULL(TIMESTAMP_DIFF(ts, LAG(ts, 1) OVER(ORDER BY ts), MINUTE), 2) > 1 gap
    FROM `project.dataset.table` 
  )
)
GROUP BY grp
-- ORDER BY grp

有结果

Row data_island  
1   2019-03-21 00:00:29 - 2019-03-21 00:02:29    
2   2019-03-21 00:04:29 - 2019-03-21 00:05:29