Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/231.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
PhP,MySql-优化代码_Php_Mysql_Optimization - Fatal编程技术网

PhP,MySql-优化代码

PhP,MySql-优化代码,php,mysql,optimization,Php,Mysql,Optimization,我不是一个伟大的php程序员(我来自C++)。我只使用php来输入数据库 我有一个包含以下内容的数据库: UserId (an unique int) AsyncPointsAverage (float) AsyncPointsAverageRank (a position based on the value immediately above) AsyncPointsRecentAverage (float an average for the last 5 tests only) Asyn

我不是一个伟大的php程序员(我来自C++)。我只使用php来输入数据库

我有一个包含以下内容的数据库:

UserId (an unique int)
AsyncPointsAverage (float)
AsyncPointsAverageRank (a position based on the value immediately above)
AsyncPointsRecentAverage (float an average for the last 5 tests only)
AsyncPointsRecentAverageRank (a position based on the value immediately above)
该表中大约有1000-1500个条目。每天早上和下午有5个人参加一项测试,这会影响他们的总体平均水平和最近的平均水平。(这在别处更新了,但这里没有显示。)在为这5个人计算之后,所有1000-1500人的排名都将生效,因此我在下面编写了代码。它是最优的吗

我最关心的是,我正在做一个MySql更新,大约1000次。那很棒吗?我应该换一种方式吗?(也可以自由地优化函数中的任何其他代码。正如我所说,我来自C++背景,所以不知道PHP的细微差别。)
//按数组项1排序
函数重新分级($a,$b)
{
如果($a[1]=$b[1])返回0;
其他回报($a[1]>$b[1]?1:-1);
}
//按数组项2排序
函数重新排序($a,$b)
{
如果($a[2]=$b[2])返回0;
其他回报($a[2]>$b[2]?1:-1);
}
函数重新存储($db)
{
$i=0,$j=0;
$usersARR=null;
$stmt=$db->prepare(“从studenttable中选择UserId、AsyncPointsAverage、AsyncPointsRecentAverage”);
$stmt->execute();
如果($stmt&&isset($stmt)&&$stmt->rowCount()>0)
{
$i=0;
而(($row=$stmt->fetch(PDO::fetch_ASSOC)))
{
$usersARR[$i][0]=intval($row['UserId');
$usersARR[$i][1]=floatval($row['AsyncPointsAverage']);
$usersARR[$i][2]=floatval($row['AsyncPointsRecentAverage']);
$i++;
}
}
$stmt->closeCursor();//mysql\u free\u结果等效
//第一次通过$j==3将按平均值进行排名,将该排名填入$usersARR[][3]位置
//$j==4的第二次传递按AveragerRecent进行排名,用该排名填充位置$usersARR[][4]
对于($j=3,$j 0)
{
//首先,平均得分最高的人排名第一
$usersARR[$count-1][$j]=1;//位置$j由秩填充
//现在从第二个循环开始向下循环
对于($i=$count-2,$rank=1;$i>=0;$i--)
{
//只有在下一个排名严格低于上一个的情况下才能更改排名,否则将共享相同的排名
如果($usersARR[$i][$iCompare]<$usersARR[$i+1][$iCompare])$rank=$count-$i;//否则保持相同的排名,因为它们相等
$usersARR[$count-1][$j]=$rank;
}
}
}
//现在$usersARR中填充了正确的排名,它们与$UserId关联
//现在,我们必须将所有这些排名放入数据库
$count=count($usersARR);
对于($i=0;$i<$count;$i++)
{
$stmt=$db->prepare(“更新学生表集合AsyncPointsAverageRank=:AsyncPointsAverageRank,AsyncPointsRecentAverageRank=:AsyncPointsRecentAverageRank”
“其中UserId=:UserId”);
$stmt->execute(数组(':AsyncPointsAverageRank'=>$usersARR[$i][3],
':AsyncPointsRecentAverageRank'=>$usersARR[$i][4],
':UserId'=>$usersARR[$i][0]);
}
}

您需要如何使用排名?也许你不需要?它们可能很容易计算:

SELECT COUNT(*) 
FROM studenttable 
WHERE AsyncPointsAverage > $currentUserVariableAsyncPoints
要显示前10名:

SELECT * FROM studenttable ORDER BY AsyncPointsAverage DESC LIMIT 0,10
等等

编辑:

要用位置号显示完整的排名,您可以在PHP中进行(您已经有了它-在循环中获取行,只需显示
$i++
变量)。或者您可以尝试使用纯SQL(我个人更喜欢):


为了扩展Mark的答案,您不需要在每次添加测试结果时重新计算排名。它当然是功能性的,但不是最优的。最好的方法是在显示排名时计算排名。如果你想让学生有相同的结果和相同的排名,你可以用PHP计算排名

SQL:

PHP:

$stmt=$db->prepare(“见上文…”);
$stmt->execute();
如果($stmt&&isset($stmt)&&$stmt->rowCount()){
$rank=1;
$last_grade=-1;
而(($row=$stmt->fetch(PDO::fetch_ASSOC))){
$usersARR[$i][0]=intval($row['UserId');
$usersARR[$i][1]=floatval($row['AsyncPointsAverage']);
$usersARR[$i][2]=floatval($row['AsyncPointsRecentAverage']);
如果($usersARR[$i][1]<$last\u年级){
$rank++;
}
$usersARR[$i][3]=$rank;
$last_grade=$usersARR[$i][1];
}
}

如果您想改为按最近平均值下单,只需更改读取的字段和下单依据字段。

您可以使用事务并执行所有更新。我不确定MyISAM是否支持事务,但InnoDb支持。您的代码是注入安全的,对于任何现代数据库服务器来说,运行一千个小的更新查询都没有问题。我会说你很好。如果您希望进一步优化,则说明您在错误的StackExchange站点上。:)没有仔细查看你的问题,因为你做的方式似乎很好,但是,仅仅为了“讨论目的”,如果你想避免在你的数据库中有一千个更新,你应该考虑另一个“排名”系统,就像你的表中的一个列,指的是“前一个”或“下一个元素”。这样,您的排名更新只会影响“重新分类”的项目和邻居…学生将能够登录到系统并通过查看页面查看他们的排名(查看他们与其他人的比较情况)。他们还可以登录到自己的个人页面,该页面将显示他们的总体排名和最近排名。我认为在每次测试后计算一次排名是最好的方法,而不是每次计算每个学生每天数千次的浏览量。(每天只有2次考试,每次考试只有5名学生。)你的排名会是m吗
SELECT * FROM studenttable ORDER BY AsyncPointsAverage DESC LIMIT 0,10
SET @rank=0; SELECT @rank := @rank +1 AS rank, UserId, AsyncPointsAverage
FROM studenttable
ORDER BY AsyncPointsAverage DESC 
SELECT
    UserId,
    AsyncPointsAverage,
    AsyncPointsAverageRank
FROM
    studenttable
ORDER BY
    AsyncPointsAverage DESC
$stmt = $db->prepare("SEE ABOVE...");
$stmt->execute();

if( $stmt && isset( $stmt ) && $stmt->rowCount() ) {
    $rank = 1;
    $last_grade = -1;

    while( ( $row = $stmt->fetch( PDO::FETCH_ASSOC ) ) ) {
        $usersARR[$i][0] = intval($row['UserId']);
        $usersARR[$i][1] = floatval($row['AsyncPointsAverage']);
        $usersARR[$i][2] = floatval($row['AsyncPointsRecentAverage']);

        if( $usersARR[$i][1] < $last_grade ) {
            $rank++;
        }

        $usersARR[$i][3] = $rank;

        $last_grade = $usersARR[$i][1];
    }
}