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

SQL查询最高报名容量比课程,聚合函数内嵌SELECT是否可行?

问题解答

现有写法存在的问题

你给出的写法无法实现需求,核心问题如下:

  • 缺少GROUP BY子句:HAVING是对分组后的聚合结果做过滤,你没有对课程ID分组,聚合逻辑完全不成立,语法层面也会报错。
  • 字段使用错误:子查询中出现了不存在的id_course字段,你的关联表中仅存在id_class字段关联课程ID。
  • 统计逻辑错误:子查询的WHERE条件加入了sc2.id_student=s.id,实际统计的是单个学生在对应课程的报名次数,完全不是你需要的「课程总报名人数」。
  • HAVING语法错误:HAVING后需要跟布尔判断条件,你仅写了MAX(xxx)没有判断规则,无法通过语法校验。

关于聚合函数内使用子查询的说明

语法层面确实支持在聚合函数中嵌套子查询,但你当前的场景完全不需要这么写,这种写法会对每条关联记录都触发一次子查询,数据量较大时性能会非常差。

更优的实现方案

核心思路

先统计每门课程的总报名人数,计算「报名人数/课程容量」的占比,再筛选出占比最高的课程即可,逻辑清晰性能也更好。

通用实现(兼容所有支持标准SQL的数据库)

SELECT c.id AS class_id
FROM class c
LEFT JOIN student_class sc ON c.id = sc.id_class
GROUP BY c.id, c.capacity
HAVING COUNT(sc.id_student) / c.capacity = (
    SELECT MAX(occupy_rate)
    FROM (
        SELECT COUNT(sc2.id_student) / c2.capacity AS occupy_rate
        FROM class c2
        LEFT JOIN student_class sc2 ON c2.id = sc2.id_class
        GROUP BY c2.id, c2.capacity
    ) AS rate_table
)

简化实现(支持CTE和窗口函数的数据库,如MySQL8.0+、PostgreSQL等)

-- 先计算每门课的占用率
WITH class_occupy_rate AS (
    SELECT 
        c.id AS class_id,
        COUNT(sc.id_student) / c.capacity AS occupy_rate
    FROM class c
    LEFT JOIN student_class sc ON c.id = sc.id_class
    GROUP BY c.id, c.capacity
)
-- 筛选占比最高的课程,支持返回所有并列最高的结果
SELECT class_id
FROM class_occupy_rate
WHERE occupy_rate = (SELECT MAX(occupy_rate) FROM class_occupy_rate)

补充说明

  • 这里用LEFT JOIN是为了包含无人报名的课程(占比为0),如果你的需求不需要统计这类课程,换成INNER JOIN即可。
  • 如果student_class表允许同一学生重复报名同一门课,统计人数时把COUNT(sc.id_student)换成COUNT(DISTINCT sc.id_student)即可。
  • 两种写法都支持返回所有占比并列最高的课程,不会漏数据。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 16:00:01