SELECT / GROUP BY – 时间段(10秒,30秒等)
我有一个表(MySQL),每隔n秒捕获一次样本。 该表有许多列,但是重要的是两个:时间戳(types为TIMESTAMP)和计数(types为INT)。
我想要做的是在一定的时间范围内获得计数列的总和和平均值。 例如,我每2秒logging一次样本,但是我希望在所有样本的10秒或30秒窗口中,所有样本的计数列的总和。
这是一个数据的例子:
+ --------------------- + ----------------- + | time_stamp | count | + --------------------- + ----------------- + | 2010-06-15 23:35:28 | 1 | | 2010-06-15 23:35:30 | 1 | | 2010-06-15 23:35:30 | 1 | | 2010-06-15 23:35:30 | 942 | | 2010-06-15 23:35:30 | 180 | | 2010-06-15 23:35:30 | 4 | | 2010-06-15 23:35:30 | 52 | | 2010-06-15 23:35:30 | 12 | | 2010-06-15 23:35:30 | 1 | | 2010-06-15 23:35:30 | 1 | | 2010-06-15 23:35:33 | 1468 | | 2010-06-15 23:35:33 | 247 | | 2010-06-15 23:35:33 | 1 | | 2010-06-15 23:35:33 | 81 | | 2010-06-15 23:35:33 | 16 | | 2010-06-15 23:35:35 | 1828 | | 2010-06-15 23:35:35 | 214 | | 2010-06-15 23:35:35 | 75 | | 2010-06-15 23:35:35 | 8 | | 2010-06-15 23:35:37 | 1799 | | 2010-06-15 23:35:37 | 24 | | 2010-06-15 23:35:37 | 11 | | 2010-06-15 23:35:37 | 2 | | 2010-06-15 23:35:40 | 575 | | 2010-06-15 23:35:40 | 1 | | 2010-06-17 10:39:35 | 2 | | 2010-06-17 10:39:35 | 2 | | 2010-06-17 10:39:35 | 1 | | 2010-06-17 10:39:35 | 2 | | 2010-06-17 10:39:35 | 1 | | 2010-06-17 10:39:40 | 35 | | 2010-06-17 10:39:40 | 19 | | 2010-06-17 10:39:40 | 37 | | 2010-06-17 10:39:42 | 64 | | 2010-06-17 10:39:42 | 3 | | 2010-06-17 10:39:42 | 31 | | 2010-06-17 10:39:42 | 7 | | 2010-06-17 10:39:42 | 246 | + --------------------- + ----------------- +
我想(根据上面的数据)的输出应该是这样的:
+ --------------------- + ----------------- + | 2010-06-15 23:35:00 | 1 | #这是00 - 30秒范围内的总和 | 2010-06-15 23:35:30 | 7544 | #这是30 - 60秒范围内的总和 | 2010-06-17 10:39:35 | 450 | #这是30 - 60秒范围内的总和 + --------------------- + ----------------- +
我已经使用GROUP BY收集这些数字,第二次,或者一分钟,但我似乎无法弄清楚的语法,以获得次分钟或范围秒GROUP BY命令正常工作。
我主要是要使用此查询来从这个表中的数据虹吸到另一个表。
谢谢!
GROUP BY UNIX_TIMESTAMP(time_stamp) DIV 30
或者说出于某种原因,你想以20秒为间隔将它们分组,这将是DIV 20
等。要改变GROUP BY
值之间的界限,你可以使用
GROUP BY (UNIX_TIMESTAMP(time_stamp) + r) DIV 30
其中r
是小于30的文字非负整数
GROUP BY (UNIX_TIMESTAMP(time_stamp) + 5) DIV 30
应该在hh:mm:05和hh:mm:35之间以及在hh:mm:35和hh:mm + 1:05之间给出总和。
我在我的项目中尝试了Hammerite的解决scheme,但在系列中缺less样本的地方效果不佳。 下面是一个查询的例子,它应该从metric_table中select时间戳(ts),用户名和平均度量值,并将结果按27分钟的时间间隔进行分组:
select min(ts), user_name, sum(measure) / 27 from metric_table where ts between date_sub('2015-03-17 00:00:00', INTERVAL 2160 MINUTE) and '2015-03-17 00:00:00' group by unix_timestamp(ts) div 1620, user_name order by ts, user_name ;
注意:27分钟(select)= 1620秒(按组),2160分钟= 3天(即时间范围)
当我针对一个时间序列运行这个查询时,不规则地logging了样本(换句话说,对于任何给定的时间戳,没有保证find所有用户名的度量值),结果没有按照时间间隔标记每27分钟)。 我怀疑这是由于min(ts)在某些组中返回的时间戳大于预期的时间间隔(ts0 + i *间隔)。 我修改了以前的查询到这个:
select from_unixtime(unix_timestamp(ts) - unix_timestamp(ts) mod 1620) as ts1, user_name, sum(measure) / 27 from metric_table where ts between date_sub('2015-03-17 00:00:00', INTERVAL 2160 MINUTE) and '2015-03-17 00:00:00' group by ts1, user_name order by ts1, user_name ;
即使样品丢失,它也能正常工作。 我认为这是因为一旦math时间移动select它保证ts1将与时间步骤一致。
解决scheme
要平均你喜欢的任何时间间隔,你可以把你的dt转换为时间戳,并按照你的时间间隔(在这个例子中是7秒)进行分组。
select FROM_UNIXTIME( UNIX_TIMESTAMP(dt_record) - UNIX_TIMESTAMP(dt_record) mod 7 ) as dt, avg(1das4hrz) from `meteor-m2_msgi` where dt_record>='2016-11-13 05:00:00' and dt_record < '2016-11-13 05:02:00' group by FROM_UNIXTIME( UNIX_TIMESTAMP(dt_record) - UNIX_TIMESTAMP(dt_record) mod 7);
为了展示它的工作原理,我准备了一个请求,显示计算结果。
select dt_record, minute(dt_record) as mm, SECOND(dt_record) as ss, UNIX_TIMESTAMP(dt_record) as uxt, UNIX_TIMESTAMP(dt_record) mod 7 as ux7, FROM_UNIXTIME( UNIX_TIMESTAMP(dt_record) - UNIX_TIMESTAMP(dt_record) mod 7) as dtsub, column from `yourtable` where dt_record>='2016-11-13 05:00:00' and dt_record < '2016-11-13 05:02:00'; +---------------------+--------------------+ | dt | avg(column) | +---------------------+--------------------+ | 2016-11-13 04:59:43 | 25434.85714285714 | | 2016-11-13 05:00:42 | 5700.728813559322 | | 2016-11-13 05:01:41 | 950.1016949152543 | | 2016-11-13 05:02:40 | 4671.220338983051 | | 2016-11-13 05:03:39 | 25468.728813559323 | | 2016-11-13 05:04:38 | 43883.52542372881 | | 2016-11-13 05:05:37 | 24589.338983050846 | +---------------------+--------------------+ +---------------------+-----+-----+------------+------+---------------------+----------+ | dt_record | mm | ss | uxt | ux7 | dtsub | column | +---------------------+------+-----+------------+------+---------------------+----------+ | 2016-11-13 05:00:00 | 0 | 0 | 1479002400 | 1 | 2016-11-13 04:59:59 | 36137 | | 2016-11-13 05:00:01 | 0 | 1 | 1479002401 | 2 | 2016-11-13 04:59:59 | 36137 | | 2016-11-13 05:00:02 | 0 | 2 | 1479002402 | 3 | 2016-11-13 04:59:59 | 36137 | | 2016-11-13 05:00:03 | 0 | 3 | 1479002403 | 4 | 2016-11-13 04:59:59 | 34911 | | 2016-11-13 05:00:04 | 0 | 4 | 1479002404 | 5 | 2016-11-13 04:59:59 | 34911 | | 2016-11-13 05:00:05 | 0 | 5 | 1479002405 | 6 | 2016-11-13 04:59:59 | 34911 | | 2016-11-13 05:00:06 | 0 | 6 | 1479002406 | 0 | 2016-11-13 05:00:06 | 33726 | | 2016-11-13 05:00:07 | 0 | 7 | 1479002407 | 1 | 2016-11-13 05:00:06 | 32581 | | 2016-11-13 05:00:08 | 0 | 8 | 1479002408 | 2 | 2016-11-13 05:00:06 | 32581 | | 2016-11-13 05:00:09 | 0 | 9 | 1479002409 | 3 | 2016-11-13 05:00:06 | 31475 | +---------------------+-----+-----+------------+------+---------------------+----------+
任何人都可以build议更快的事
很奇怪,但在这里使用的解决scheme:
在给定时间内每5分钟的平均数据
我们可以build议像这样的:
select convert( (min(dt_record) div 50)*50 - 20*((convert(min(dt_record), datetime) div 50) mod 2),
datetime)as dt,avg(1das4hrz)from meteor-m2_msgi
其中dt_record> ='2016-11-13 05:00:00'和dt_record <'2016-11-14 00:00:00'group by convert(dt_record, datetime)div 50;
select ( convert( min(dt_record), datetime) div 50)*50 - 20*( (convert(min(dt_record), datetime) div 50) mod 2 ) as dt, avg(column) from `your_table` where dt_record>='2016-11-13 05:00:00' and dt_record < '2016-11-14 00:00:00' group by convert(dt_record, datetime) div 50;
50是因为NORMAL分钟的1/2有30秒而'INTEGER DATE FORMAT'假设我们除以50