2010-11-01 167 views
2

我有一个表log,其中有列id,值,类别和时间戳。假设表充满这样的:在mysql中计算5分钟间隔的平均值

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()的列值生成一个表指定的检查,从最后的检查条目开始。对于检查= 1的输出应该是这样的:

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

输出为check = 2应该是这样的:

ID AVERAGE 
---------- 
1 10 

什么是接近最好的方法?我有MySQL的基本知识,但这让我感到困惑。查询的一部分会是这样,我想(不包括5分钟的时间间隔分组):

SELECT avg(value) FROM log WHERE check = .. 

我如何使用时间戳来产生间隔5分钟的平均值?任何帮助是极大的赞赏。

+0

我不知道mysql,但从看看GROUP BY是做什么开始的。 – Pointy 2010-11-01 21:37:43

+1

你能解释一下'check = 1'的功能吗?我没有得到这部分。 – 2010-11-01 21:44:11

+0

check = 1仅表示列值为1的列检查的平均间隔时间为5分钟 – Ivo 2010-11-01 21:51:29

回答

1

参见this

select AVG(value), from_unixtime(ROUND(timestamp/(60*5)) * 60 * 5) as rounded_time 
from table 
group by rounded_time 
+0

这几乎让我在那里!我应该提到时间戳采用日期时间格式,因此:从'log'中选择AVG(值),from_unixtime(ROUND(unix_timestamp(timestamp)/(60 * 5))* 60 * 5)作为rounded_time,其中'check' = round_time的1组几乎让我在那里。我希望5分钟的间隔从特定检查的最后时间戳记条目开始,而不是00,05,10等。例如,检查2间隔期应该是10:19,10:14等。 – Ivo 2010-11-01 22:07:20

+0

@Ivo:可能类似于'set @ min_1:= min(from_unixtime ...'然后在你的选择做'... ROUND((timestamp + @ min_1)/(60 * 5)...' – Xodarap 2010-11-02 01:09:00

0

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

首先在MySQL创建存储过程,像这样(从这里http://ondra.zizka.cz/stranky/programovani/sql/mysql_stored_procedures.texy改性原始来源):

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 ; 

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

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; 

问候, 伊沃

0

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

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) 
0
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等等。分钟平均容易。