对于每一行,计算MySQL中最后20行的平均值


For each row, compute average for last 20 rows in MySQL

我需要使用PHP脚本在csv文件中计算从谷歌金融导入的股票价格的平均值和标准差。我可以将这些csv文件导入到mysql中的不同表中。我计划把每种存货都放在一张单独的桌子上,这样一开始就不那么复杂了。

在电子表格中,计算最后n行的运行平均值是相当容易的。然而,一旦我导入MySQL,我就会对如何计算从第20行开始的每一行的最后20行的平均值感到震惊(显然知识较少)。

当我从谷歌金融导入时,我的表结构如下:

+-------------+---------+
|     id      |  close  |
+-------------+---------+
| a1447128000 | 1353.5  |
| 1           | 1356.2  |
| 2           | 1352.65 |
| 3           | 1355.65 |
| 4           | 1354.2  |
| 5           | 1356    |
| 6           | 1351    |
| 7           | 1352.5  |
| 8           | 1350    |
| 9           | 1349.3  |
| 10          | 1343.6  |
| 11          | 1342.4  |
| 12          | 1340.7  |
| 13          | 1338.5  |
| 14          | 1340.5  |
| 15          | 1338.5  |
| 16          | 1340    |
| 17          | 1335.25 |
| 18          | 1340.5  |
| 19          | 1341    |
| 20          | 1338.95 |
| 21          | 1334    |
| 22          | 1326.5  |
| 23          | 1320.1  |
| 24          | 1318    |
+-------------+---------+

我正在努力实现这样的输出:

+-------------+---------+-----------+--------------------+
|     id      |  close  |  average  | standard deviation |
+-------------+---------+-----------+--------------------+
| a1447128000 | 1353.5  |           |                    |
| 1           | 1356.2  |           |                    |
| 2           | 1352.65 |           |                    |
| 3           | 1355.65 |           |                    |
| 4           | 1354.2  |           |                    |
| 5           | 1356    |           |                    |
| 6           | 1351    |           |                    |
| 7           | 1352.5  |           |                    |
| 8           | 1350    |           |                    |
| 9           | 1349.3  |           |                    |
| 10          | 1343.6  |           |                    |
| 11          | 1342.4  |           |                    |
| 12          | 1340.7  |           |                    |
| 13          | 1338.5  |           |                    |
| 14          | 1340.5  |           |                    |
| 15          | 1338.5  |           |                    |
| 16          | 1340    |           |                    |
| 17          | 1335.25 |           |                    |
| 18          | 1340.5  |           |                    |
| 19          | 1341    | 1346.5975 | 6.885664002        |
| 20          | 1338.95 | 1345.87   | 6.886588415        |
| 21          | 1334    | 1344.76   | 6.921155973        |
| 22          | 1326.5  | 1343.4525 | 7.729917124        |
| 23          | 1320.1  | 1341.675  | 8.7418605          |
| 24          | 1318    | 1339.865  | 9.660513703        |
+-------------+---------+-----------+--------------------+

正如您正确地注意到的,对于第19行,平均值将是最后20行。对于行id 20,平均值将是最后20行。。。等等。

我甚至想知道php的foreach循环是否可以用于遍历每一行并获得最后20行的平均值,但当我尝试时,我完全迷失了方向。

我无法获得任何关于这方面的线索(无论是MySQL还是PHP)。如有任何关于如何解决此问题的建议,我们将不胜感激。

下面的代码大致显示了的功能

$averages = array();
while($row = $result->fetch_assoc())
{
    $sum = 0;
    $arraySize = array_push($averages,$row['close']);
    if($arraySize > 20)
    {
        array_shift($averages)
    }
    foreach($averages as $value)
    {
        $sum += $value;
    }
    $average = $sum / $arraySize
}

从代码开头的一个空数组开始,在MySQL Results循环的每次迭代中,您都会使用array_push,它还会在添加值后返回数组的大小。然后检查这个值,如果它大于20,您会使用array_shift,它会将所有值下移1,去掉第一个值

如果您希望它在数组中的值数小于20时不进行计算,只需将foreach及其下面的行包装在if语句中即可

    $variableLoop=0;
    while($row = $result->fetch_assoc())
    {
        $array[]=$row['close'];
        if($variableLoop >= 19){
            $result=0;
            for($i=$variableLoop-19;$i<=$variableLoop;$i++){
                $result+=$array[$i];
            }
            $average=$result/20;
            //print or whatever you need to do with average and result
        }
        $variableLoop++;
    }

不确定如何显示平均值,但这应该有效。

$values=array();$sum=0;$i=0;while($row=$result->fetch_assoc()){$values[]=$row[关闭];$sum+=$row[关闭];如果($i>19){$sum-=$values[$i-20];$row[‘average’]=$sum/20;}}

这是对我有用的完整代码。感谢@Memor-X、@origenes和@Terminus,因为这段代码是使用他们的响应开发的。我甚至用同样的逻辑计算了标准偏差。

$averages = array();
while($row = $result->fetch_assoc())
{
      $sum = 0;
    $arraySize = array_push($averages,$row['close']);
    if($arraySize > 20)
    {
        array_shift($averages);
    }
if($arraySize > 19) {
    $sum = array_sum($averages);
    $average = $sum /20;
    echo "average: " .$average ."<br/>";
    }
    $sumOfDiff =0;
if($arraySize > 19) {
    foreach($averages as $valueitem)
    {
        $sumOfDiff += ($valueitem - $average)*($valueitem - $average);
    }
    $variance = $sumOfDiff/20;
    $stddev = sqrt($variance);
    $upperband = $average + ($stddev *2);
    $lowerband = $average - ($stddev *2);
    echo "variance: " .$variance."<br/>";
    echo "standard deviation: " .$stddev ."<br/>";
    }
}