表结构
- 学生表student(id,name)
- 课程表course(id,name)
- 成绩表student_course(sid,cid,score)
先建表:
create table student( id int not null auto_increment, name char(10) not null, primary key(id) );
create table course( id int not null auto_increment, name char(10) not null, primary key(id) );
create table student_course( sid int not null, cid int not null, score int not null, foreign key (sid) references student(id), foreign key (cid) references course(id) );
|
再构造数据:
insert into student(name) values ('张三'),('李四'); insert into course(name) values('语文'),('数学'); insert into student_course values(1,1,80),(1,2,90),(2,1,90),(2,2,70);
|
问题
1、查询选了课程的人数
select count(distinct cid) from student_scourse;
|
2、查询每门课程被选修的学生数
select cid, count(sid) from student_course group by cid;
|
3、查询至少选修了两门课的学生的学号以及选课的数量
select sid, count(cid) as res from student_course group by sid having res>=2;
|
4、查询去重后的学生的信息
select id,name from student group by id,name;
select distinct(id),name from student;
|
以上两种写法等价
5、查询student表中重名的学生,结果包含id和name,按name,id升序
select id,name from student where name in( select name from student group by name having(count(name)>1) ) order by name,id;
|
最重要的工作就是解决重名问题。按名字分组, 看哪一组行数大于1,就说明这一组代表的所有人,都是重名的。
6、在student_course表中查询平均分不及格的学生,列出学生id和平均分
select sid, avg(score) from student_course group by sid having(avg(score)<60);
|
where后面不能跟聚集函数;having后面可以。
7、查询两门课程以上不及格的学生的学号及其平均成绩
select sid,avg(score) from student_course where score<60 group by sid having count(cid)>2;
|
8、查询各科成绩最高和最低的分
select cid,max(score),min(score) from student_course group by cid;
|
9、查询平均成绩大于60分的学生的学号和平均成绩
select sid,avg(score) as res from student_course group by sid having res>60;
|
10、在student_course表中查询每门课成绩都不低于80的学生id
select sid from student_course where sid not in ( select sid from student_course where score < 80 group by sid );
|
反向思想,先找出有课程低于80分的学生,这些学生去重后,其补集就是目标要找的学生。
group by候面不能跟where,where后面能跟group by。
11、查询课程编号为0002的总成绩
select sum(score) from student_course where sid = 0002;
|
12、查询每个学生的总成绩,结果列出学生姓名和总成绩
select name, sum(score) from student, student_course where student.id=student_course.sid group by student.id;
|
如果使用上面的sql会过滤掉没有成绩的人。需要考虑有的学生缺考,没有成绩。更保险的做法应该是使用 左外连接。
select name,sum(score) from student left join student_course on student.id=student_course.sid group by sid;
|
13、查询id为1的课程里,得分最高的学生的信息
select * from student where id=( select sid from student_course where cid=1 order by score desc limit 0,1 );
|
14、查询id为1的课程里,得分第三高的学生的信息
select * from student where id=( select sid from student_course where cid=1 group by score order by score desc limit 2,1 );
|
要group by分组来去重,因为要考虑到这么一种情况:想找第三大的时间,但有多个人并列在第二大。
我们要以分数大小为依据;如果只排序一下就取,那是以人数为依据的,第三个人不一定是第三大。
15、总成绩最高的学生,结果列出学生id和总成绩
select sid,sum(score) as res from student_course group by sid order by res limit 0,1;
|
16、在student_course表查询各科成绩最高的学生,结果列出学生id、课程id和对应的成绩
select sid,cid,score from student_course group by cid order by score limit 0,1;
select sid,cid,max(score) from student_course group by cid;
|
上面两条语句作用相同,但都是不恰当的。因为 使用了group by的查询字段只能是group by中的字段或者聚集函数或者是每个分组内均相同的字段。 虽然不会报错,但是sid是无效的,如果去掉sid的话只能查出每门课程的最高分,不包含学生id。 本题的正确解法是使用相关嵌套查询:
select * from student_course as x where score>= (select max(score) from student_course where cid=x.cid);
|