从一组范围计算并发性

时间:2016-02-16 19:13:22

标签: sql google-app-engine google-bigquery

我有一组包含开始时间戳和持续时间的行。我想使用重叠或并发执行各种摘要。

例如:每日峰值并发,峰值并发分组在另一列上。

示例数据:

timestamp,duration
2016-01-01 12:00:00,300
2016-01-01 12:01:00,300
2016-01-01 12:06:00,300

我想知道这段时间的高峰期是12:01:00-12:05:00,同时为2。

关于如何使用BigQuery实现这一点的任何想法,或者更少令人兴奋的Map / Reduce工作?

2 个答案:

答案 0 :(得分:1)

对于每分钟分辨率,会话长度最长为255分钟:

SELECT session_minute, COUNT(*) c
FROM (
  SELECT start, DATE_ADD(start, i, 'MINUTE') session_minute FROM (
    SELECT * FROM (
      SELECT TIMESTAMP("2015-04-30 10:14") start, 7 minutes
    ),(
      SELECT TIMESTAMP("2015-04-30 10:15") start, 12 minutes
    ),(
      SELECT TIMESTAMP("2015-04-30 10:15") start, 12 minutes
    ),(
      SELECT TIMESTAMP("2015-04-30 10:18") start, 12 minutes
    ),(
      SELECT TIMESTAMP("2015-04-30 10:23") start, 3 minutes
    ) 
  ) a
  CROSS JOIN [fh-bigquery:public_dump.numbers_255] b
  WHERE a.minutes>b.i
)
GROUP BY 1
ORDER BY 1

enter image description here

答案 1 :(得分:1)

  

第1步 - 首先,您需要找到所有期间(开始和结束)   各自的并发条目

SELECT ts AS start, LEAD(ts) OVER(ORDER BY ts) AS finish, 
       SUM(entry) OVER(ORDER BY ts) AS concurrent_entries
FROM (
  SELECT ts, SUM(entry)AS entry 
  FROM 
    (SELECT ts, 1 AS entry FROM yourTable),
    (SELECT DATE_ADD(ts, duration, 'second') AS ts, -1 AS entry FROM yourTable)
  GROUP BY ts
  HAVING entry != 0
)
ORDER BY ts  

假设输入如下

(SELECT TIMESTAMP('2016-01-01 12:00:00') AS ts, 300 AS duration),
(SELECT TIMESTAMP('2016-01-01 12:01:00') AS ts, 300 AS duration),
(SELECT TIMESTAMP('2016-01-01 12:06:00') AS ts, 300 AS duration),
(SELECT TIMESTAMP('2016-01-01 12:07:00') AS ts, 300 AS duration),
(SELECT TIMESTAMP('2016-01-01 12:10:00') AS ts, 300 AS duration),
(SELECT TIMESTAMP('2016-01-01 12:11:00') AS ts, 300 AS duration)

上述查询的输出看起来会像这样:

start                       finish                      concurrent_entries   
2016-01-01 12:00:00 UTC     2016-01-01 12:01:00 UTC     1    
2016-01-01 12:01:00 UTC     2016-01-01 12:05:00 UTC     2    
2016-01-01 12:05:00 UTC     2016-01-01 12:07:00 UTC     1    
2016-01-01 12:07:00 UTC     2016-01-01 12:10:00 UTC     2    
2016-01-01 12:10:00 UTC     2016-01-01 12:12:00 UTC     3    
2016-01-01 12:12:00 UTC     2016-01-01 12:15:00 UTC     2    
2016-01-01 12:15:00 UTC     2016-01-01 12:16:00 UTC     1    
2016-01-01 12:16:00 UTC     null                        0   

您可能仍然希望稍微优化一下 - 但主要是它可以满足您的需求

  

第2步 - 现在您可以根据上述结果进行任何统计

例如整个时期的峰值:

SELECT 
  start, finish, concurrent_entries, RANK() OVER(ORDER BY concurrent_entries DESC) AS peak
FROM (
  SELECT ts AS start, LEAD(ts) OVER(ORDER BY ts) AS finish, 
         SUM(entry) OVER(ORDER BY ts) AS concurrent_entries
  FROM (
    SELECT ts, SUM(entry)AS entry FROM 
      (SELECT ts, 1 AS entry FROM yourTable),
      (SELECT DATE_ADD(ts, duration, 'second') AS ts, -1 AS entry FROM yourTable)
    GROUP BY ts
    HAVING entry != 0
  )
)
ORDER BY peak