在一个时间范围内分成5分钟的时间间隔

我想要做的mySQL命令有一些困难。

SELECT a.timestamp, name, count(b.name) FROM time a, id b WHERE a.user = b.user AND a.id = b.id AND b.name = 'John' AND a.timestamp BETWEEN '2010-11-16 10:30:00' AND '2010-11-16 11:00:00' GROUP BY a.timestamp 

这是我目前的输出声明。

 timestamp name count(b.name) ------------------- ---- ------------- 2010-11-16 10:32:22 John 2 2010-11-16 10:35:12 John 7 2010-11-16 10:36:34 John 1 2010-11-16 10:37:45 John 2 2010-11-16 10:48:26 John 8 2010-11-16 10:55:00 John 9 2010-11-16 10:58:08 John 2 

我如何将它们分成5分钟的间隔结果?

我想我的输出是像

 timestamp name count(b.name) ------------------- ---- ------------- 2010-11-16 10:30:00 John 2 2010-11-16 10:35:00 John 10 2010-11-16 10:40:00 John 0 2010-11-16 10:45:00 John 8 2010-11-16 10:50:00 John 0 2010-11-16 10:55:00 John 11 

这适用于每个时间间隔。

PostgreSQL的

 SELECT TIMESTAMP WITH TIME ZONE 'epoch' + INTERVAL '1 second' * round((extract('epoch' from timestamp) / 300) * 300) as timestamp, name, count(b.name) FROM time a, id WHERE … GROUP BY round(extract('epoch' from timestamp) / 300), name 

MySQL的

 SELECT timestamp, -- not sure about that name, count(b.name) FROM time a, id WHERE … GROUP BY UNIX_TIMESTAMP(timestamp) DIV 300, name 

您应该使用GROUP BY UNIX_TIMESTAMP(time_stamp) DIV 300而不是round(../ 300),因为四舍五入,我发现有些logging被计入两个分组结果集中。

对于postgres ,我发现使用它更简单,更准确

date_trunc

function,如:

 select name, sum(count), date_trunc('minute',timestamp) as timestamp FROM table WHERE xxx GROUP BY name,date_trunc('minute',timestamp) ORDER BY timestamp 

你可以提供各种决议,如“分钟”,“小时”,“天”等…到date_trunc。

我遇到了同样的问题。

我发现很容易以任何时间间隔进行分组,只需以秒为单位划分纪元 ,然后舍入或使用地板来获得余数。 所以如果你想在5分钟内得到间隔,你可以使用300秒


     SELECT COUNT(*)cnt, 
     to_timestamp(floor((提取(来自timestamp_column的'epoch')/ 300))* 300) 
    在时区“UTC”作为interval_alias
     FROM TABLE_NAME GROUP BY interval_alias

 
 interval_alias cnt
 ------------------- ----  
 2010-11-16 10:30:00 2
 2010-11-16 10:35:00 10
 2010-11-16 10:45:00 8
 2010-11-16 10:55:00 11 

这将按选定的分钟间隔正确返回数据; 但是,它不会返回不包含任何数据的时间间隔。 为了得到这些空的区间,我们可以使用函数generate_series 。





 SELECT generate_series(MIN(date_trunc('hour',timestamp_column)),
 max(date_trunc('minute',timestamp_column)),'5m')作为interval_alias FROM TABLE_NAME

结果:

 interval_alias       
 -------------------    
 2010-11-16 10:30:00  
 2010-11-16 10:35:00
 2010-11-16 10:40:00   
 2010-11-16 10:45:00
 2010-11-16 10:50:00   
 2010-11-16 10:55:00   

现在为了得到结果间隔零发生,我们只是外部连接两个结果集


     SELECT series.minute as interval,coalesce(cnt.amnt,0)as count from 
        (
        SELECT count(*)amnt,
        to_timestamp(floor((提取(来自timestamp_column的'epoch')/ 300))* 300)
       在时区“UTC”作为interval_alias
        from TABLE_NAME group by interval_alias
        )cnt

    正确的join 
        (    
        SELECT generate_series(min(date_trunc('hour',timestamp_column)),
        max(date_trunc('minute',timestamp_column)),'5m')作为TABLE_NAME的分钟 
        )系列

  在series.minute = cnt.interval_alias

最终结果将包括所有5分钟间隔的系列甚至那些没有价值的系列。

间隔计数
 ------------------- ----  
 2010-11-16 10:30:00 2
 2010-11-16 10:35:00 10
 2010-11-16 10:40:00 0
 2010-11-16 10:45:00 8
 2010-11-16 10:50:00 0 
 2010-11-16 10:55:00 11 

通过调整generate_series的最后一个参数,可以很容易地改变这个间隔。 在我们的例子中,我们使用'5m',但它可以是我们想要的任何时间间隔

该查询将如下所示:

 SELECT DATE_FORMAT( MIN(timestamp), '%d/%m/%Y %H:%i:00' ) AS tmstamp, name, COUNT(id) AS cnt FROM table GROUP BY ROUND(UNIX_TIMESTAMP(timestamp) / 300), name 

你可能不得不把你的时间戳分解成ymd:HM,并使用DIV 5将分钟分成5分钟,

 select year(a.timestamp), month(a.timestamp), hour(a.timestamp), minute(a.timestamp) DIV 5, name, count(b.name) FROM time a, id b WHERE a.user = b.user AND a.id = b.id AND b.name = 'John' AND a.timestamp BETWEEN '2010-11-16 10:30:00' AND '2010-11-16 11:00:00' GROUP BY year(a.timestamp), month(a.timestamp), hour(a.timestamp), minute(a.timestamp) DIV 12 

…然后在客户端代码中输出出现你喜欢的方式。 或者,如果你喜欢,你可以使用sql concat操作符来build立整个datestring,而不用单独的列。

 select concat(year(a.timestamp), "-", month(a.timestamp), "-" ,day(a.timestamp), " " , lpad(hour(a.timestamp),2,'0'), ":", lpad((minute(a.timestamp) DIV 5) * 5, 2, '0')) 

…然后分组

这个怎么样:

 select from_unixtime(unix_timestamp(timestamp) - unix_timestamp(timestamp) mod 300) as ts, sum(value) from group_interval group by ts order by ts ; 

我发现用MySQL可能正确的查询如下:

 SELECT SUBSTRING( FROM_UNIXTIME( CEILING( timestamp /300 ) *300, '%Y-%m-%d %H:%i:%S' ) , 1, 19 ) AS ts_CEILING, SUM(value) FROM group_interval GROUP BY SUBSTRING( FROM_UNIXTIME( CEILING( timestamp /300 ) *300, '%Y-%m-%d %H:%i:%S' ) , 1, 19 ) ORDER BY SUBSTRING( FROM_UNIXTIME( CEILING( timestamp /300 ) *300, '%Y-%m-%d %H:%i:%S' ) , 1, 19 ) DESC 

让我知道你的想法。

 select CONCAT(CAST(CREATEDATE AS DATE),' ',datepart(hour,createdate),':',ROUNd(CAST((CAST((CAST(DATEPART(MINUTE,CREATEDATE) AS DECIMAL (18,4)))/5 AS INT)) AS DECIMAL (18,4))/12*60,2)) AS '5MINDATE' ,count(something) from TABLE group by CONCAT(CAST(CREATEDATE AS DATE),' ',datepart(hour,createdate),':',ROUNd(CAST((CAST((CAST(DATEPART(MINUTE,CREATEDATE) AS DECIMAL (18,4)))/5 AS INT)) AS DECIMAL (18,4))/12*60,2)) 

不知道你是否仍然需要它。

 SELECT FROM_UNIXTIME(FLOOR((UNIX_TIMESTAMP(timestamp))/300)*300) AS t,timestamp,count(1) as c from users GROUP BY t ORDER BY t; 

2016-10-29 19:35:00 | 2016-10-29 19:35:50 | 4 |

2016-10-29 19:40:00 | 2016-10-29 19:40:37 | 5 |

2016-10-29 19:45:00 | 2016-10-29 19:45:09 | 6 |

2016-10-29 19:50:00 | 2016-10-29 19:51:14 | 4 |

2016-10-29 19:55:00 | 2016-10-29 19:56:17 | 1 |