CodeIgniter科目成绩密集排名查询WHERE过滤失效问题
问题原因
两个核心问题导致排名错误:
- SQL语句WHERE条件写法错误:条件两侧都用反引号包裹了同名字段,等价于
字段=字段的恒真判断,完全没有使用传入的科目ID参数做过滤,因此查询返回了所有科目的成绩,导致跨科目混合排序。 - 视图层排名逻辑未做去重处理,无法实现同分同名次的密集排名效果。
修复方案
模型层修改
修复SQL参数绑定逻辑,使用CodeIgniter的参数绑定机制传入科目ID,既实现科目过滤,也避免SQL注入风险,替换后的代码如下:
public function GetSubjectPosScores($exam_group_class_batch_exam_subject_id) { $sql = " SELECT `get_tot_score` FROM `exam_group_exam_results` WHERE `exam_group_class_batch_exam_subject_id` = ? ORDER BY `get_tot_score` DESC "; $query = $this->db->query($sql, [$exam_group_class_batch_exam_subject_id]); return $query->result(); }
控制器层
现有控制器仅做参数透传和模型调用,逻辑正确,无需修改。
视图层修改
补充分数去重、数组索引重置逻辑,实现标准密集排名(同分同排名,后续排名不空位),替换后的代码如下:
<?php $scores2 = $CI->GetSubjectPosScores($exam_group_class_batch_exam_subject_id); $scores = array_column($scores2, 'get_tot_score'); // 去重实现密集排名,重置索引避免键名不连续导致排名计算错误 $uniqueSortedScores = array_values(array_unique($scores)); $pos = array_search($exam_result_value->get_tot_score, $uniqueSortedScores); $number = $pos + 1; echo $CI->ordinal($number); ?>
修复后效果
修复后查询会先按传入的科目ID过滤成绩,仅在单个科目内做分数降序和排名计算,输出结果符合预期:
student_id | subject_id | get_tot_score | Position --------------------------------------------------- 11 | 1 | 76 | 2nd 12 | 1 | 90 | 1st 28 | 6 | 89 | 1st 30 | 6 | 70 | 2nd
内容的提问来源于stack exchange,提问作者KasimaEse
相关产品推荐
相关产品推荐

