关于sql:在mysql中计算5分钟间隔的平均值

calculate averages for 5 min intervals in mysql

我有一个表log,其中包含列ID,值,类别和时间戳。假设表是这样填充的:

1
2
3
4
5
6
7
8
ID   VALUE        CATEGORY   TIMESTAMP
-----------------------------------------------
1     10             1       2010-11-1 10:00:00
2     20             1       2010-11-1 10:03:00
3     15             2       2010-11-1 10:15:00
4     05             2       2010-11-1 10:19:00
5     30             1       2010-11-1 10:24:00
6     12             1       2010-11-1 10:30:00

现在,我想从最后一个检查条目开始,以5分钟的间隔为指定的检查生成一个带有avg()的列值表。 check = 1的输出应类似于:

1
2
3
4
5
ID AVERAGE
----------
1  12
2  30
3  15

check = 2的输出应类似于:

1
2
3
ID AVERAGE
----------
1  10

解决此问题的最佳方法是什么?我具有MySQL的基本知识,但这使我感到困惑。我想查询的一部分将是这样的(没有5分钟的间隔分组):

1
SELECT avg(VALUE) FROM log WHERE CHECK = ..

如何使用时间戳生成5分钟间隔平均值?任何帮助将不胜感激。


请参阅此。

1
2
3
SELECT AVG(VALUE),  from_unixtime(ROUND(TIMESTAMP / (60*5)) * 60 * 5) AS rounded_time
FROM TABLE
GROUP BY rounded_time


1
2
3
4
5
6
SELECT
   DATE_FORMAT((atimestamp),
      concat( '%Y-%m-%d %H:' ,
            CAST(round(MINUTE(atimestamp)) -  round(MINUTE(atimestamp)) % 5 AS CHAR))
   )AS rounded_time
   ,avg(price) , COUNT(*) FROM TABLE

这样,您可以获得5,10,15,30等。平均分钟很容易。


也许稍后,但最短的查询将是:

1
2
 SELECT ID, AVG(VALUE) AS average, DATE_FORMAT(MIN(TIMESTAMP), '%Y-%m-%d %H:%i:00') AS tmstamp
   FROM yourtable GROUP BY round(UNIX_TIMESTAMP(TIMESTAMP) DIV 60*5)

如果有人对这里感兴趣,这是我想出的答案(在同事的帮助下)。

首先在MysQL中创建一个存储过程,如下所示(从此处修改原始资源http://ondra.zizka.cz/stranky/programovani/sql/mysql_stored_procedures.texy):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
DELIMITER $$
CREATE PROCEDURE generate_series (
  iFrom TIMESTAMP, iTo TIMESTAMP, iStep INTEGER )

body:
BEGIN

  DROP TEMPORARY TABLE IF EXISTS stamp_series;
  CREATE TEMPORARY TABLE stamp_series ( stamp TIMESTAMP NOT NULL);

  IF iFrom IS NULL OR iTo IS NULL OR iStep IS NULL
    THEN LEAVE body; END IF;

  SET @iMax = iFrom;
  SET @iMin = iTo;

  InsertLoop: LOOP
    INSERT INTO stamp_series SET stamp = @iMax;
    SET @iMax = DATE_SUB( @iMax, INTERVAL iStep SECOND);
    IF @iMin > @iMax THEN LEAVE InsertLoop; END IF;
  END LOOP;

END; $$
DELIMITER ;

然后实际的查询是这样的:

1
2
CALL generate_series( timestamp1 , timestamp2 , 300);
SELECT stamp, DATE_SUB(stamp, INTERVAL 5 MINUTE) AS stamp_min_5, (  SELECT COALESCE( AVG(VALUE), 0) FROM `table` WHERE `category` = 1 AND TIMESTAMP <= stamp AND TIMESTAMP > DATE_SUB(stamp, INTERVAL 5 MINUTE) ) AS gem FROM stamp_series;

关于,
伊沃