PHP while循环中使用IF语句查询学生成绩等级错误排查
问题排查结果
你的等级全返回A的核心问题有3个:
- 等级匹配SQL逻辑完全错误:原SQL里的IF判断对每一条gradings记录,只要maxscore大于等于分数就返回等级、小于等于也返回等级,等于所有等级行都会返回结果;而你调用
fetch()只取结果集的第一行,gradings表第一行是maxscore=100的A等级,所以不管多少分都会固定返回A,根本没有做分数区间的匹配。 - 存在PDO用法不规范问题:你直接把参数拼接到SQL字符串里,没有用预处理绑定参数,存在SQL注入风险;同时循环内每次单独查询等级,属于典型的N+1查询问题,性能很差。
- 存在代码语法和HTML结构错误:开头定义的计数器变量是
$counter(小写c),循环递增时写的是$Counter(大写C),PHP变量大小写敏感会触发报错;表格HTML结构混乱,循环内重复输出<tbody>标签,末尾多写了</thead>闭合标签,会导致页面渲染异常。
修正方案
等级匹配逻辑说明
根据你给出的gradings表规则(等级按maxscore从高到低排序),正确的匹配规则是:找到所有maxscore >= 学生分数的等级记录中,maxscore值最小的那条,对应的gname就是匹配的正确等级:
- 100分:满足>=100的最小maxscore是100,对应A
- 80分:满足>=80的最小maxscore是80,对应B
- 40分:满足>=40的最小maxscore是40,对应D
完全符合你的预期结果。
修正后代码
直接用一次联表SQL查询出所有需要的数据,不需要循环内重复查库,同时修正变量和HTML结构问题,用PDO参数绑定:
$counter = 0; $stid = 1; // 联表一次查询所有成绩及对应等级,避免N+1查询 $sql = "SELECT er.subject, er.score, ( SELECT g.gname FROM gradings g WHERE g.maxscore >= er.score ORDER BY g.maxscore ASC LIMIT 1 ) as grade FROM examresults er WHERE er.id = :stid"; $stmt = $conn->prepare($sql); // 参数绑定避免SQL注入 $stmt->bindParam(':stid', $stid, PDO::PARAM_INT); $stmt->execute(); echo '<h3 class="text-center">Examination Results</h3>'; echo '<table class="table table-bordered"> <thead> <tr style="background-color: #F2F2F2;"> <td class="text-bold">Sl No</td> <td class="text-bold">Subject</td> <td class="text-bold">Score</td> <td class="text-bold">Grade</td> </tr> </thead> <tbody>'; while($row = $stmt->fetch(PDO::FETCH_ASSOC)) { echo '<tr role="row" class="odd"> <td>'.++$counter.'</td> <td style="padding-left: 50px;">'.$row['subject'].'</td> <td>'.$row['score'].'</td> <td>'.$row['grade'].'</td> </tr>'; } echo '</tbody> </table>';
验证结果
运行修正后的代码,输出结果完全符合预期:
- English 100分 → 等级A
- Math 80分 → 等级B
- Bios 40分 → 等级D
内容的提问来源于stack exchange,提问作者Mostan
相关产品推荐
相关产品推荐

