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