You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何获取单科最高分对应学生?SQL查询返回错误学生信息问题

问题描述

需要查询特定科目下的最高分,并显示该分数对应的学生姓名。当前编写的SQL查询能获取班级内该科目的最高分,但无法匹配到正确的student_id,导致显示的学生姓名并非最高分对应的学生。

原查询代码

$subjectMaxQry = $this->db->query(
        "SELECT `student_id`, max(".$totField.") AS highest, 
                (SELECT firstname FROM students WHERE students.id = student_id) AS firstname, 
                (SELECT lastname FROM students WHERE students.id = student_id) AS lastname 
        FROM ".$table." 
        WHERE `session_id` = '".$sch_setting->session_id."' 
        AND `class_id` = '".$class_id."' 
        AND `subject_id` = '".$subName['sub_id']."'");

$highestMark = $subjectMaxQry->row_array();

问题原因

原SQL存在逻辑错误:未指定GROUP BY的情况下,将student_id与聚合函数MAX()同时放在SELECT中,数据库会返回查询结果集中任意一条记录的student_id(而非对应最高分的那条),导致关联查询到的学生姓名错误。

解决方法

方法1:子查询匹配最高分

先通过子查询获取该科目的最高分,再查询对应分数的学生记录并关联学生表:

SELECT m.student_id, s.firstname, s.lastname, m.`$totField` AS highest
FROM `$table` m
JOIN students s ON m.student_id = s.id
WHERE m.session_id = '$sch_setting->session_id'
  AND m.class_id = '$class_id'
  AND m.subject_id = '$subName[sub_id]'
  AND m.`$totField` = (
    SELECT MAX(`$totField`)
    FROM `$table`
    WHERE session_id = '$sch_setting->session_id'
      AND class_id = '$class_id'
      AND subject_id = '$subName[sub_id]'
  )

方法2:使用CodeIgniter查询构造器(更安全,避免SQL注入)

推荐用框架查询构造器拼接SQL,规避直接变量拼接的注入风险:

// 第一步:获取该科目的最高分
$maxMark = $this->db->select_max($totField)
                    ->where('session_id', $sch_setting->session_id)
                    ->where('class_id', $class_id)
                    ->where('subject_id', $subName['sub_id'])
                    ->get($table)
                    ->row()->$totField;

// 第二步:查询对应最高分的学生信息
$subjectMaxQry = $this->db->select('m.student_id, s.firstname, s.lastname, m.'.$totField.' AS highest')
                          ->from($table.' m')
                          ->join('students s', 'm.student_id = s.id')
                          ->where('m.session_id', $sch_setting->session_id)
                          ->where('m.class_id', $class_id)
                          ->where('m.subject_id', $subName['sub_id'])
                          ->where('m.'.$totField, $maxMark)
                          ->get();

$highestMark = $subjectMaxQry->row_array();

方法3:使用窗口函数(适用于MySQL 8.0+等现代数据库)

如果数据库支持窗口函数,可通过RANK()直接筛选最高分记录:

SELECT student_id, firstname, lastname, highest
FROM (
    SELECT m.student_id, s.firstname, s.lastname, m.`$totField` AS highest,
           RANK() OVER (ORDER BY m.`$totField` DESC) AS rnk
    FROM `$table` m
    JOIN students s ON m.student_id = s.id
    WHERE m.session_id = '$sch_setting->session_id'
      AND m.class_id = '$class_id'
      AND m.subject_id = '$subName[sub_id]'
) t
WHERE rnk = 1;

内容的提问来源于stack exchange,提问作者Esepebbles

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 15:24:39