【问题标题】:mysql- Averaging values every n row with same idmysql-每n行具有相同ID的平均值
【发布时间】:2014-12-09 14:19:40
【问题描述】:

我尝试在 Perl 脚本中执行某些操作,但我想知道是否有更简单快捷的方法可以直接通过 SQL 执行此操作。

首先,这是我从中获取值的表的摘录(时间列是时间戳):

|  Computer  |    TIME    |   CPU   |
| Computer-1 | 1418115601 |      67 | 
| Computer-2 | 1418115601 |      31 | 
| Computer-1 | 1418115601 |      39 | 
| Computer-2 | 1418115601 |      39 | 
| Computer-1 | 1418115601 |      37 | 
| Computer-2 | 1418115601 |      38 | 
| Computer-1 | 1418115601 |      54 | 
| Computer-2 | 1418115601 |       0 | 
| Computer-1 | 1418115601 |      52 | 
| Computer-2 | 1418116501 |      28 | 
| Computer-1 | 1418116501 |      30 | 
| Computer-3 | 1418116501 |      33 | 
| Computer-1 | 1418116501 |      23 | 
| Computer-2 | 1418116501 |       5 |
| Computer-2 | 1418116301 |       5 | 

现在,我在此表中有 500 或 600K 行。我用它来创建图表。我只是从 Perl 脚本中检索值,然后生成一个图表,但无论如何。问题是这些措施每 5 分钟采取一次。因此,如果我创建一整天的图表,每台计算机将有 288 个“点”((60/5)*24)。

我的问题是,如果我想要更大的图表粒度,假设只有 96 个点(每 15 分钟测量一次),我该怎么做?

在这种情况下,我必须找到一种方法来告诉“对于每个相同的 ID(在这种情况下是计算机),取你找到的最后 3 个值(我按日期排序,所以应该没有问题),平均他们,然后给我结果”。

问题是我不知道该怎么做,而且 TIME 列也可能是个问题。他将如何处理?是否可以精确诸如“在对 CPU 的最后 3 个值进行平均后,让最后一行的 TIME 填充新的平均行”?或者实际上我也可以平均时间,这仍然有效......

提前谢谢大家:)

编辑:

有些人想要一个我想要的输出示例,所以这里是: (在这个例子中,我们假设我只有 2 台计算机,每台计算机 6 个值)

如果有正常的请求,我会得到这个

mysql> SELECT Computer, TIME, CPU FROM myTable order by date;

|  Computer  |    TIME    |   CPU   |
| Computer-1 | 1418115601 |      10 | 
| Computer-2 | 1418115601 |      30 | 
| Computer-1 | 1418115701 |      15 | 
| Computer-2 | 1418115701 |      40 | 
| Computer-1 | 1418115801 |      15 | 
| Computer-2 | 1418115801 |      50 | 
| Computer-1 | 1418115901 |      12 | 
| Computer-2 | 1418115901 |      50 | 
| Computer-1 | 1418116101 |      10 | 
| Computer-2 | 1418116101 |      40 | 
| Computer-1 | 1418116201 |      11 | 
| Computer-2 | 1418116201 |      35 | 

我想要具有相同 ID(计算机)的最后 3 个值的平均值,所以:

|  Computer  |    TIME    |   CPU   |
| Computer-1 | 1418115801 |   13.33 | 
| Computer-2 | 1418115801 |      40 |
| Computer-1 | 1418116201 |      11 | 
| Computer-2 | 1418116201 |   41.66 | 

【问题讨论】:

  • 您能否编辑您的问题并提供您想要的结果?
  • 嗯...我正在设想添加一个用户定义的变量,该变量在每个不同的时间间隔增加一。然后使用它和一个 mod 运算符,如果余数为 1,则返回那些行......这实际上将返回第一组时间,第 4 次,第 7 次,第 10 次等等......这就是你的意思之后?
  • SELECT FLOOR(time/900)*900, AVG(thing) FROM my_table GROUP BY FLOOR(time/900)*900
  • CPU 中的逗号是小数点还是值分隔符?
  • 逗号是十进制的,我是欧洲人,我们使用逗号,但我会用一点你是对的,这样会更清楚

标签: mysql sql average


【解决方案1】:

您需要模仿 MySQL 中不可用的分析函数 ROW_NUMBER() OVER (PARTITION BY)。你在 MySQL 中使用变量。

我们将每台计算机的行编号为 0、1、2、3、4、5、6 等。然后除以 3 得到 0、0、0、1、1、1、2 等。因此我们得到要聚合的分组标准:

select computer, max(time), avg(cpu)
from
(
  select 
    @row_number := case when @computer = computer then @row_number + 1 else 0 end as row_number,
    @computer := computer as computer,
    time, 
    cpu
  from mytable
  cross join (select @row_number := -1, @computer := '') as t
  order by computer, time
) as t
group by computer, row_number div 3
order by computer, row_number div 3;

我在 Pinal Dave 的博客中找到了 row_number 技术:http://blog.sqlauthority.com/2014/03/09/mysql-reset-row-number-for-each-group-partition-by-row-number/

【讨论】:

  • 哇,我很确定这确实有效!我正在详细检查,因为我在现实中有更多的价值,但到目前为止一切都很好:D 我明天会回来检查答案是否有效! (唯一缺少的是最后一个“)”之后的“as t”。否则你会得到一个错误。
  • 我很高兴这对你有用。感谢派生表需要别名的提示。我大部分时间都在使用 Oracle,它不需要它(我认为这是对 SQL 标准的方便扩展)。我会更新我的答案。
猜你喜欢
  • 1970-01-01
  • 2017-01-13
  • 2022-01-08
  • 1970-01-01
  • 1970-01-01
  • 2021-11-08
  • 2021-01-01
  • 2011-10-17
相关资源
最近更新 更多