如何通过mysql cusor中的索引访问一行?

时间:2018-01-27 20:51:56

标签: mysql stored-procedures sql-view

我有一个包含以下信息的视图:

date, n1, n2, n3, n4, day, month, year, some_id, unix_timesamp, mean, std
'29/5/2007', '28', '5', '0', '0.1786', '29', '5', '2007', '5', '1180411981', null, null
...
...

我想计算过去n4y的平均值和标准偏差。视图的结果已按天分组。

如果我使用标准编程语言,我的算法将如下所示:

//For each line
for(int i = 0; i < rows.length; i++){
  //We have advanced enough days to compute average
  //and std
  if(i > y){
     //Stores the values of the past y days
     float[] values = new float[y];
     int z = 0;
     //Loop over the past y days
     for(int j = i - y; j < i; j++){
        values[z] = rows[j].n4;
        z++;
     }
     //compute mean and std
     rows[i].mean = mean(values);
     rows[i].std = std(values);
   }
}

现在,我无法在mysql内部找到这样做(是的,我真的必须)。我开始玩here所描述的光标和临时表,但我不知道如何访问内循环所需的给定行。我也尝试使用子查询作为内部循环,但视图包含~100k行,每行需要约0.3秒才能重新查询视图(使用函数仅选择y天并计算均值和给定行的标准。)

视图提供的内容会不断更新,因此必须在用户计算平均值和标准值。请求。我无法计算一次并将其存储在专用表中。

有什么建议吗?

2 个答案:

答案 0 :(得分:0)

为什么要使用游标?使用基于集合的查询更容易表达:

select avg(n4), stddev(n4)
from t
where date >= curdate() - interval by day;

为获得最佳性能,您需要(date, n4)上的索引。

答案 1 :(得分:0)

您正在描述的行为需要window functions,这些行为将添加到MySQL 8.0和MariaDB 10.2中。截至2018年1月,这两个版本都没有作为稳定版本提供。

一旦稳定版本的数据库中提供了这些功能,我相信这种语法将起作用。 (我根据文档猜测,因为我没有安装MySQL 8.0 alpha进行测试。)

SELECT
    date,
    AVG(n4) OVER w,
    STDDEV(n4) OVER w
FROM table_name
WINDOW w AS (
    ORDER BY date
    ROWS BETWEEN y PRECEDING AND CURRENT ROW
)