各专业平均成绩较高的学生
Posted
技术标签:
【中文标题】各专业平均成绩较高的学生【英文标题】:Student with greater average grades by major 【发布时间】:2021-01-16 09:09:55 【问题描述】:表格和数据:
CREATE TABLE major
(
id INT PRIMARY KEY,
name VARCHAR(200)
);
insert into major values
(101, 'Computing'),
(102, 'Arquitecture');
CREATE TABLE student
(
id INT PRIMARY KEY,
name VARCHAR(200),
major_id INT,
foreign key(major_id) references major(id)
);
insert into student values
(1001, 'Claude', 101),
(1002, 'John', 101),
(1003, 'Peter', 102);
CREATE TABLE course
(
id INT PRIMARY KEY,
name VARCHAR(200)
);
insert into course values
(901, 'Databases'),
(902, 'Java'),
(903, 'Artificial Intelligence'),
(904, 'OOP');
CREATE TABLE grades
(
student_id INT,
course_id INT,
grade integer,
primary key (student_id, course_id),
foreign key(student_id) references student(id),
foreign key(course_id) references course(id)
);
insert into grades values
(1001, 903, 95),
(1001, 904, 88),
(1002, 901, 76),
(1002, 903, 82),
(1003, 902, 87);
预期:
| student | major | grade |
| ---------- | -------------| ----- |
| Peter | Architecture | 87 |
| Claude | Computing | 91.5 |
换句话说:检索每个专业的高年级学生。
游乐场here.
如果可能,不带 TOP,LIMIT。
如果可能的话,使用旧的 ANSI SQL 以及使用窗口函数。
引擎 mysql,但不是必需的。
我的做法#1:
-- average grade by student
select s.name as Student, m.name as Major, avg(g.grade) as Average
from student s
inner join grades g on (s.id = g.student_id)
inner join major m on (m.id = s.major_id)
group by s.id
但不需要约翰:
| Student | Major | Average |
| ------- | ------------ | ------- |
| Claude | Computing | 91.5000 |
| John | Computing | 79.0000 |
| Peter | Arquitecture | 87.0000 |
我的做法#2:
-- Max average grade by career; lacks student
select a.major, max (a.average) as Average
from (select s.name as Student, m.name as Major, avg(g.grade) as average
from student s
inner join grades g on (s.id = g.student_id)
inner join major m on (m.id = s.major_id)
group by s.id) a
group by a.major;
但缺少学生栏。
| major | Average |
| ------------ | ------- |
| Arquitecture | 87.0000 |
| Computing | 91.5000 |
谢谢。
【问题讨论】:
排除约翰的标准是什么? @ntalbs John 正在学习计算,但 Cluade 的平均成绩更高。必须按专业分组,然后选择平均分较高的学生,例如 max(avg(grade))。 那么,是否要检索每个专业的高年级学生? 不对。已编辑。 【参考方案1】:如果您运行的是 MySQL 8.0,您可以使用rank()
:
select *
from (
select s.name as student, m.name as major, avg(g.grade) as average,
rank() over(partition by m.id order by avg(g.grade) desc) rn
from student s
inner join grades g on s.id = g.student_id
inner join major m on m.id = s.major_id
group by s.id, m.id
) t
where rn = 1
注意事项:
rank()
允许绑定
连接条件的括号是多余的
【讨论】:
如果克劳德和约翰的平均成绩相同怎么办? db-fiddle.com/f/3mr4GRz5tJ3ofFeQcTZvF8/7 @Antoniosánchez:正如我所说,rank() 允许平局,所以它给了 Claude 和 John。你想要哪个结果? 只选择其中任何一个,好像学生信息无关紧要,查询是“按职业划分的平均成绩更高”,无论哪个学生。 @AntonioSánchez:如果是这样,请使用row_number()
而不是rank()
。【参考方案2】:
你可以结合你的两个查询:
select a.* FROM
( select s.name as Student, m.name as Major, avg(g.grade) as Average
from student s
inner join grades g on (s.id = g.student_id)
inner join major m on (m.id = s.major_id)
group by s.id
) a
INNER JOIN
(select a.major, max (a.average) as Average
from (select s.name as Student, m.name as Major, avg(g.grade) as average
from student s
inner join grades g on (s.id = g.student_id)
inner join major m on (m.id = s.major_id)
group by s.id) a
group by a.major ) b
ON a.major=b.major and a.average=b.average
【讨论】:
一般来说,SELECT 子句中的所有非聚合列都必须包含在 GROUP BY 子句中——尽管我接受学生只能拥有一个专业的前提。 如果克劳德和约翰的平均成绩相同怎么办? db-fiddle.com/f/3mr4GRz5tJ3ofFeQcTZvF8/6 那你要么需要使用top,要么切换到window函数。 GMB 已经使用窗口函数提供了答案db-fiddle.com/f/cABESz8puGeFSfGfAytPtu/0【参考方案3】:对于旧版本的 MySQL...
SELECT x.*
FROM
( SELECT m.name major
, s.name student
, AVG(grade) avg_grade
FROM major m
JOIN student s
ON s.major_id = m.id
JOIN grades g
ON g.student_id = s.id
GROUP
BY major
, student
) x
JOIN
(
SELECT major
, MAX(avg_grade) avg_grade
FROM
( SELECT m.name major
, s.name student
, AVG(grade) avg_grade
FROM major m
JOIN student s
ON s.major_id = m.id
JOIN grades g
ON g.student_id = s.id
GROUP
BY major
, student
)n
GROUP
BY major
) y
ON y.major = x.major
AND y.avg_grade = x.avg_grade
| major | student | avg_grade |
| ------------ | ------- | --------- |
| Arquitecture | Peter | 87.0000 |
| Computing | Claude | 91.5000 |
---
View on DB Fiddle
【讨论】:
如果克劳德和约翰的平均成绩相同怎么办? db-fiddle.com/f/3mr4GRz5tJ3ofFeQcTZvF8/8 @AntonioSánchez 在这种情况下你会期待什么? 只选择其中任何一个,好像学生信息无关紧要,查询是“按职业划分的平均成绩更高”,无论哪个学生。 好吧,就是这样! :-)以上是关于各专业平均成绩较高的学生的主要内容,如果未能解决你的问题,请参考以下文章
输入两个学生的学号姓名和成绩,输出成绩较高的学生的学号姓名和成绩