【问题标题】:running average in mysqlmysql中的运行平均值
【发布时间】:2017-01-27 11:00:06
【问题描述】:

我有如下表格

id   timestamp  speed
1    11:00:01   100
2    11:05:01   110
3    11:10:01   90
4    11:15 :01  80

我需要像下面这样计算移动平均线

id   timestamp  speed average
1    11:00:01   100   100 
2    11:05:01   110   105
3    11:10:01   90    100
4    11:15:01   80    95

我尝试了什么

SELECT 
*,
(select avg(speed) from tbl t where tbl.timestamp<=t.timestamp) as avg
FROM 
tbl

起初看起来很简单,但是当表上的数据膨胀时,它就太慢了

有更快的方法吗?

【问题讨论】:

  • 时间增量是否始终不变?否则使用avg 是不正确的。

标签: mysql sql average


【解决方案1】:

您的查询是计算运行平均值的一种方法:

SELECT t.*,
       (select avg(speed) from tbl tt where tt.timestamp <= t.timestamp) as avg
FROM tbl t;

替代方法是使用变量:

select t.*, (sum_speed / cnt) as running_avg_speed
from (select t.*, (@rn := @rn + 1) as cnt, (@s := @s + speed) as sum_speed
      from tbl t cross join
           (select @rn := 0, @s := 0) params
      order by timestamp
     ) t;

tbl(timestamp) 上的索引应该会进一步提高性能。

【讨论】:

    【解决方案2】:

    MySQL 是否支持窗口函数?

    select
      id, timestamp, speed,
      avg (speed) over (order by timestamp) as average
    from tbl
    

    如果它不起作用,这可能会起作用,尽管我怀疑它是否有效:

    select
      min (t1.id) as id, t1.timestamp, min (t1.speed) as speed,
      avg (t2.speed)
    from
      tbl t1
      join tbl t2 on
        t2.id <= t1.id
    group by
      t1.timestamp
    order by
      t1.timestamp
    

    【讨论】:

    • 是的,它适用于给定的数据,但对于这个时间戳必须以增量顺序作为 id。
    • 啊,我明白了。然后我将分组列更改为时间戳 - 也许可以这样做。
    • MySQL不支持窗口函数,所以答案不正确。
    【解决方案3】:

    或者在 GL 的两个答案之间巧妙地插入(无论如何在性能方面)...

    SELECT x.*, AVG(y.speed) avg
      FROM my_table x
      JOIN my_table y
        ON y.id <= x.id
     GROUP 
        BY x.id;
    

    【讨论】:

      【解决方案4】:

      一个简单的并发解决方案怎么样?

      SET @summ=0; SET @counter=0;SELECT *,(@counter := @counter +1) as cnt, (@summ := @summ+speed) as spd, (@summ/@counter) AS avg FROM tbl;
      

      【讨论】:

        猜你喜欢
        • 2010-12-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-02-19
        相关资源
        最近更新 更多