【问题标题】:Calculate average from data only stored in MySQL on change计算仅存储在 MySQL 中的数据变化的平均值
【发布时间】:2014-10-23 07:17:00
【问题描述】:

我们有一个数据库,我们只存储数据值和时间戳(在 MySQL 中作为一行)当数据值更改时。因此数据库中的时间戳之间没有固定的间隔。该表如下所示:

MySQLTimestamp    Data
2014-10-01 18:01  1
2014-10-03 16:13  2
2014-10-07 15:45  1
2014-10-09 10:08  3

问题:我们想要计算随时间变化的平均值,假设数据值继续为 2,直到数据库中下一行的值发生变化。

简单的 AVG 无法解决问题,因为它只会计算行数之间的平均值。在下一行表明数据值发生变化之前,这不会计算一个值可以在很长一段时间内继续保持相同的值。

非常感谢您的帮助!

【问题讨论】:

  • over time 是什么意思?期望的结果如何?
  • 随着时间的推移,我的意思是我需要两个日期之间的平均值。抱歉,我对此有点不清楚。所需的函数应如下所示:GetLogAvg($FromDate, $ToDate) { ..... return Avg }。我确实想在 MySQL 中完成这一切。

标签: mysql timestamp average intervals


【解决方案1】:

自加入并计算日期或时间的持续时间作为权重到Data

select 
    sum(data*duration_of_date)/sum(duration_of_date) as avg_over_date,
    sum(data*duration_of_hour)/sum(duration_of_hour) as avg_over_hour,
    sum(data*duration_of_sec)/sum(duration_of_sec) as avg_over_sec
from (
    select 
        t1.MySQLTimestamp,
        t1.data,
        min(case when t1.MySQLTimestamp<t2.MySQLTimestamp 
                 then t2.MySQLTimestamp else null end) as next_tm,
        datediff( 
            min(case when t1.MySQLTimestamp<t2.MySQLTimestamp 
                     then t2.MySQLTimestamp else null end) , 
            t1.MySQLTimestamp) as duration_of_date,
        TIME_TO_SEC(timediff( 
            min(case when t1.MySQLTimestamp<t2.MySQLTimestamp 
                     then t2.MySQLTimestamp else null end) , 
            t1.MySQLTimestamp))/60/60 as duration_of_hour,
        TIME_TO_SEC(timediff( 
            min(case when t1.MySQLTimestamp<t2.MySQLTimestamp 
                     then t2.MySQLTimestamp else null end) , 
            t1.MySQLTimestamp)) as duration_of_sec
    from 
        your_table t1
    cross join 
        your_table t2
    group by 
        t1.MySQLTimestamp, 
        t1.data
    ) as t

使用datediff 将天数间隔计算为重量。如果您想要小时或分钟作为间隔,您可以使用timediff 并将结果转换为小时、分钟或秒。

这是sql fiddle demo 和结果:

AVG_OVER_DATE   AVG_OVER_HOUR   AVG_OVER_SEC
          1.5         1.51887         1.5189

左连接的另一个版本:

select 
    sum(data*duration_of_date)/sum(duration_of_date) as avg_over_date,
    sum(data*duration_of_hour)/sum(duration_of_hour) as avg_over_hour,
    sum(data*duration_of_sec)/sum(duration_of_sec) as avg_over_sec
from (
    select 
        t1.MySQLTimestamp,
        t1.data,
        min(t2.MySQLTimestamp) as next_tm,
        datediff(min(t2.MySQLTimestamp), t1.MySQLTimestamp) as duration_of_date,
        TIME_TO_SEC(timediff(min(t2.MySQLTimestamp), t1.MySQLTimestamp))/60/60 as duration_of_hour,
        TIME_TO_SEC(timediff(min(t2.MySQLTimestamp), t1.MySQLTimestamp)) as duration_of_sec
    from 
        your_table t1
    left join 
        your_table t2
    on 
        t1.MySQLTimestamp<t2.MySQLTimestamp
    group by 
        t1.MySQLTimestamp, 
        t1.data
    ) as t

【讨论】:

  • 哇!谢啦!这个周末我会试试看,我会告诉你的!
猜你喜欢
  • 2018-03-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-12
相关资源
最近更新 更多