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

基于成绩优先级、志愿顺序与座位余量的学生院校分配实现问题

一键分配院校功能实现方案

核心实现逻辑

  • 提前批量加载所需全量数据到内存,避免循环查询数据库,大幅提升执行效率
  • 维护院校实时剩余座位字典,分配成功后立即扣减对应院校座位数,保证后续匹配的准确性
  • 严格按照分数从高到低的顺序处理学生,每个学生的志愿按order_preference升序逐个校验
  • 匹配到有剩余座位的志愿院校后,立即更新学生的分配院校字段,终止该学生的后续志愿校验;所有志愿均无空位则不为该学生分配院校
  • 引入事务保证数据一致性,分配过程出现异常可全部回滚,避免出现部分数据更新的问题

优化后完整代码

using (SqlConnection dbcon = new SqlConnection(_conString))
{
    dbcon.Open();
    // 开启事务,保证分配操作的原子性
    using (SqlTransaction tran = dbcon.BeginTransaction())
    {
        try
        {
            // 1. 查询所有成绩合格且按分数降序排列的学生
            SqlCommand scmd = new SqlCommand(
                "SELECT stud_Id, stud_fname, stud_purcentage FROM tblStudent WHERE stud_result = 'Pass' ORDER BY stud_purcentage DESC", 
                dbcon, 
                tran);
            SqlDataAdapter da = new SqlDataAdapter(scmd);
            DataTable dtPassStudents = new DataTable();
            da.Fill(dtPassStudents);

            // 2. 查询所有填报的志愿,按学生ID分组、按志愿优先级排序
            SqlCommand cmdSelection = new SqlCommand(
                "SELECT tas.stud_id, tas.Acad_id, ta.seat_available FROM tblAcademy_Selection tas JOIN tblAcademy ta ON tas.Acad_id = ta.Acad_id ORDER BY tas.stud_id, tas.order_preference ASC",
                dbcon,
                tran);
            SqlDataAdapter daSelection = new SqlDataAdapter(cmdSelection);
            DataTable dtAllSelections = new DataTable();
            daSelection.Fill(dtAllSelections);
            // 按学生ID分组存储志愿
            var studentSelections = dtAllSelections.AsEnumerable()
                .GroupBy(r => r.Field<int>("stud_id"))
                .ToDictionary(g => g.Key, g => g.ToList());

            // 3. 初始化院校剩余座位字典
            SqlCommand cmdAcademy = new SqlCommand(
                "SELECT Acad_id, seat_available FROM tblAcademy",
                dbcon,
                tran);
            SqlDataAdapter daAcademy = new SqlDataAdapter(cmdAcademy);
            DataTable dtAcademy = new DataTable();
            daAcademy.Fill(dtAcademy);
            var academySeat = dtAcademy.AsEnumerable()
                .ToDictionary(r => r.Field<int>("Acad_id"), r => r.Field<int>("seat_available"));

            // 4. 逐个处理学生分配
            foreach (DataRow studentRow in dtPassStudents.Rows)
            {
                int studId = Convert.ToInt32(studentRow["stud_Id"]);
                int? assignedAcadId = null;

                // 该学生没有填报志愿,直接跳过
                if (!studentSelections.ContainsKey(studId))
                    continue;

                // 按优先级遍历志愿
                foreach (var selectionRow in studentSelections[studId])
                {
                    int acadId = selectionRow.Field<int>("Acad_id");
                    // 院校还有剩余座位
                    if (academySeat[acadId] > 0)
                    {
                        assignedAcadId = acadId;
                        // 扣减对应院校剩余座位
                        academySeat[acadId]--;
                        break;
                    }
                }

                // 分配成功,更新学生表的acad_id字段
                if (assignedAcadId.HasValue)
                {
                    SqlCommand cmdUpdateStudent = new SqlCommand(
                        "UPDATE tblStudent SET acad_id = @AcadId WHERE stud_Id = @StudId",
                        dbcon,
                        tran);
                    cmdUpdateStudent.Parameters.AddWithValue("@AcadId", assignedAcadId.Value);
                    cmdUpdateStudent.Parameters.AddWithValue("@StudId", studId);
                    cmdUpdateStudent.ExecuteNonQuery();
                }
            }

            // 5. 更新院校表的剩余座位数
            foreach (var item in academySeat)
            {
                SqlCommand cmdUpdateAcademy = new SqlCommand(
                    "UPDATE tblAcademy SET seat_available = @SeatCount WHERE Acad_id = @AcadId",
                    dbcon,
                    tran);
                cmdUpdateAcademy.Parameters.AddWithValue("@SeatCount", item.Value);
                cmdUpdateAcademy.Parameters.AddWithValue("@AcadId", item.Key);
                cmdUpdateAcademy.ExecuteNonQuery();
            }

            // 所有操作成功,提交事务
            tran.Commit();
        }
        catch (Exception ex)
        {
            // 出现异常回滚所有操作
            tran.Rollback();
            // 可按需添加异常日志记录逻辑
            throw ex;
        }
    }
}

注意事项

  • 代码使用参数化查询,避免了SQL注入风险
  • 你的示例数据中,只有学生1(Alex)成绩合格且填报了志愿,会分配到第一志愿院校A,院校A的剩余座位从2变为1;其余合格学生没有填报志愿,不分配院校
  • 若需要支持志愿为空的学生服从调剂,可在所有志愿匹配失败后增加遍历所有剩余空位院校的逻辑

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 16:48:03