我有一个包含以下信息的视图:
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
...
...
我想计算过去n4
天y
的平均值和标准偏差。视图的结果已按天分组。
如果我使用标准编程语言,我的算法将如下所示:
//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
天并计算均值和给定行的标准。)
视图提供的内容会不断更新,因此必须在用户计算平均值和标准值。请求。我无法计算一次并将其存储在专用表中。
有什么建议吗?
答案 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
)