获得每个N组的平均值

时间:2013-12-15 20:59:14

标签: mysql sql group-by average

我看到这里的一些人有类似我现在遇到的问题......但没有任何帮助我:/

我有一个表有2列的测试。日期和整数值。 我需要平均每N个记录。 例如

Date        | Info
2013-01-01  |  210
2013-01-02  |  213
2013-01-03  |  214
2013-01-05  |  197
2013-01-06  |  192

...

让我们说N = 3

我需要使用

填充表格
Averages
212.3333 (that's the average of the 3 first Info's) (210+213+214)/3
208.0000 (213+214+197)/3
201.0000 (214+197+192)/3

我试过这个

delimiter $$
DROP PROCEDURE IF EXISTS calcAvg$$
CREATE PROCEDURE calcAvg()
begin

DECLARE v_finished INTEGER DEFAULT 0;
declare v_avg DECIMAL default 0.0;
DECLARE initial_date date;

DEClARE cr CURSOR FOR 
    select avg(i) from  (
        select t.info i
           from test t
          where date >= initial_date
            limit 3
        )as s;

-- declare NOT FOUND handler
DECLARE CONTINUE HANDLER FOR NOT FOUND SET v_finished = 1;

set initial_date = '2013-01-01';

get_avg: LOOP

    OPEN cr;

    cr_loop: LOOP

        FETCH cr INTO v_avg;

        IF v_finished = 1 THEN 
            LEAVE cr_loop;
        END IF;

        insert into result values (v_avg);

    END LOOP cr_loop;

    CLOSE cr;

    #I've to change this line... the table does not have all days
    set v_dt_ini = date_add(v_dt_ini,interval 1 DAY);
    #But the problem it's not the line yet...
    set v_finished = 0;

    if v_dt_ini > '2013-05-30' then
        leave get_avg;
    end if;

END LOOP get_avg;

end$$

在代码上我将N修正为3 问题在于,当我调用程序时...它会计算3条记录的第一个平均值...并且当再次执行光标时...它返回相同的值... 3个第一个记录......并且它不是我需要什么...

光标不会改变结果:/

3 个答案:

答案 0 :(得分:3)

SQLFiddle

SELECT date,info,(select avg(info) from
                  (select date,info,@row1:=@row1+1 as row
                   from test,(SELECT @row1:=0)r
                   order by date desc
                  )wrn1
                  where wrn1.row between wrn2.start and wrn2.end)as avg,
       start,end

FROM
    (select date,info,@row:=@row+1 as row,(@row - 2) as start,@row as end
     from test,(SELECT @row:=0)r
     order by date desc
    )wrn2
WHERE start > 0
ORDER BY date asc

这将返回

        DATE                   INFO     AVG       START     END
January, 01 2013 00:00:00+0000     210  212.3333    3        5
January, 02 2013 00:00:00+0000     213  208         2        4
January, 03 2013 00:00:00+0000     214  201         1        3

答案 1 :(得分:1)

您可以为此使用相关子查询。如果您想要最多n天,包括当前日期和之后的日期,那么这将有效:

select date, info,
       (select avg(t2.info)
        from test t2
        where datediff(t.date, t2.date) < n and
              t2.date >= t.date
       ) as avginfo
from test t;

如果你想要n个记录,包括当前的记录,那么下面的想法就可以了:

select date, info,
       (select avg(info)
        from (select t2.*
              from test t2
              where t2.date >= t.date
              order by t2.date
              limit n
             ) t3
       ) as avginfo
from test t;

但是,这会在MySQL中生成错误,我不确定如何解决它(双嵌套查询无法再识别与外部查询的相关性)。以下版本的工作方式如here所示:

select t.date, t.info, avg(t3.info)
from (select date, info,
             (select t2.date
              from test t2
              where t2.date >= t.date
              order by t2.date
              limit 1 offset 2
             ) as date3
      from test t
     ) t left outer join
     test t3
     on t3.date between t.date and t.date3
group by t.date, t.info;

答案 2 :(得分:0)

回应关于被命令的评论 - 诀窍是排序:

新值:在原始表上使用触发器 - AFTER INSERT触发器需要选择最后N个值的平均值(SELECT AVG(valuecolumn) FROM table WHERE datecolumn <= NEW.datecolumn ORDER BY datecolumn DESC LIMIT N)并将其插入到averages表中。

现有值:从前到后运行此选项并使用SELECT AVG(valuecolumn) FROM table WHERE datecolumn <= NEW.datecolumn ORDER BY datecolumn ASC LIMIT M,N,其中M来自0..count-2