在一个时间范围内分成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 |