各专业学生人数:没有学生的专业也要列出
LeetCode 580 · LEFT JOIN 计数、COUNT(列) 与 COUNT(*)、多字段排序
面试怎么回答
专业表 LEFT JOIN 学生表,按专业分组用 COUNT(s.student_id) 计数,没有学生的专业得到 0;排序写成 student_number DESC, dept_name。COUNT(*) 和 COUNT(列) 在 LEFT JOIN 场景下结果不同,这是这道题的考点。
先把这段讲顺;面试官追问时,再展开下面的原理和细节。
详细讲解
题意
学生表记录学生所属的专业 ID,专业表记录专业名称。统计每个专业的学生人数(没有学生的专业显示 0),按人数降序,人数相同按专业名升序。
表结构
- student:student_id(主键)、student_name、gender、dept_id
- department:dept_id(主键)、dept_name
思路
以专业表为主表 LEFT JOIN 学生表,按专业分组计数。计数必须用 COUNT(student_id):没有学生的专业关联出一行全 NULL 的记录,COUNT(*) 会把它算成 1,COUNT(列) 会忽略 NULL 得到 0。原解法漏了「人数相同按名字排序」这个要求。
参考解法
select dept_name ,count(student_id) student_number
from department d left join student s
on d.dept_id=s.dept_id
group by dept_name
order by student_number desc
另一种写法:补上第二排序键,并按 dept_id 分组
SELECT d.dept_name, COUNT(s.student_id) AS student_number
FROM department d
LEFT JOIN student s ON d.dept_id = s.dept_id
GROUP BY d.dept_id, d.dept_name
ORDER BY student_number DESC, d.dept_name
易错点
- 用 COUNT(*) 会让没有学生的专业显示 1。
- 按 dept_name 分组时,如果两个专业重名会被合并,按 dept_id 分组更稳。
- 别忘了第二排序键 dept_name。