98.SQL语句面试50题
# 01.课程1比课程2分数高的
- 查询"01"课程比"02"课程成绩高的学生的信息及课程分数
-- [分析] 筛选出课程号01这门课的成绩比02这门课成绩高的学生,输出这些学生的信息及课程分(表:Student,Score)——表联结
select a.*, b.s_score as 01_score, c.s_score as 02_score
from Student as a inner join Score as b on a.s_id = b.s_id and b.c_id = '01'
inner join Score as c on a.s_id = c.s_id and c.c_id = '02'
where b.s_score > c.s_score;
1
2
3
4
5
2
3
4
5
- Student表和Score表中 学生s_id相同的数据
MySQL> SELECT * FROM Student as a INNER JOIN Score as b ON a.s_id=b.s_id;
+------+--------+------------+-------+------+------+---------+
| s_id | s_name | s_birth | s_sex | s_id | c_id | s_score |
+------+--------+------------+-------+------+------+---- -----+
| 01 | 赵雷 | 1990-01-01 | 男 | 01 | 01 | 80 |
| 01 | 赵雷 | 1990-01-01 | 男 | 01 | 02 | 90 |
1
2
3
4
5
6
2
3
4
5
6
# 02.平均成绩大于等于60分
- 查询平均成绩大于等于60分的同学的学生编号和学生姓名和平均成绩
-- [分析] 要求平均成绩,就需要用group by对学生分组,然后利用聚合函数avg求出平均成绩,由于where语句中不能包含聚合函数,故再利用having语句和60分比较。
-- 输出的结果学生编号和学生姓名在student表中,成绩在score表中,故需要用到内联结。
SELECT a.s_id, a.s_name, AVG(s_score) as avg_score
FROM Student as a INNER JOIN Score as b ON a.s_id=b.s_id
GROUP BY a.s_id # 以Student表中的学生id分组
HAVING AVG(b.s_score) >= 60;
1
2
3
4
5
6
2
3
4
5
6
# 03.所有课程的总成绩
- 查询所有同学的学生编号、学生姓名、选课总数、所有课程的总成绩
-- [分析]学生编号、学生姓名在表student中;选课数可通过在表score中通过group by 学生编号后利用count(c_id)算出;所有课程的总成绩则用sum可以算出。
-- 因为要用到表student和表score,故需要对表进行联结。
SELECT a.s_id, a.s_name, count(b.c_id), SUM(b.s_score)
FROM Student as a INNER JOIN Score as b ON a.s_id = b.s_id
GROUP BY a.s_id,a.s_name;
1
2
3
4
5
2
3
4
5
- 查询 Student表和Score表中数据
MySQL> SELECT * FROM Student as a INNER JOIN Score as b on a.s_id=b.s_id;
+------+------- -+------------+------ -+------+------+---------+
| s_id | s_name | s_birth | s_sex | s_id | c_id | s_score |
+------+------ --+------------+-------+------+------+---------+
| 01 | 赵雷 | 1990-01-01 | 男 | 01 | 01 | 80 |
| 01 | 赵雷 | 1990-01-01 | 男 | 01 | 02 | 90 |
| 01 | 赵雷 | 1990-01-01 | 男 | 01 | 03 | 99 |
| 02 | 钱电 | 1990-12-21 | 男 | 02 | 01 | 70 |
| 02 | 钱电 | 1990-12-21 | 男 | 02 | 02 | 60 |
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
# 04.查询"李"姓老师的数量
-- [分析] 这里用到知识点字符串模糊查询,如:where 姓名 like '猴%' 即可查到猴什么什么。
-- 关于字符串模糊查询的知识点可查看我的另一篇文章《SQL学习笔记——汇总分析》
select count(t_name) as number
from Teacher
where t_name like '李%';
1
2
3
4
5
2
3
4
5
# 05.学过"张三"老师课的同学
-- [分析] 老师的信息在表teacher中,可通过teacher.t_id与表course联结,
-- 再通过course.c_id与表score联结,
-- 再再通过score.s_id与表student联结,查找出上过张三老师课的同学的信息。
SELECT s.*,a.t_name
FROM Teacher as a INNER JOIN Course as b on a.t_id = b.t_id
INNER JOIN Score as c ON b.c_id = c.c_id
INNER JOIN Student as s ON c.s_id = s.s_id
WHERE a.t_name = '张三'
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
# 06.学过01和02两门课程同学
- 学过编号为"01"并且也学过编号为"02"的课程的同学的信息
-- [分析]由于既要学过01课程的,又要学过02课程的,所以共需要联结两次才能达到筛选效果
SELECT * FROM Student # 显示这些学生的信息
WHERE s_id in (
SELECT a.s_id FROM Student as a INNER JOIN Score as b ON a.s_id = b.s_id AND b.c_id = '01' # 查询所有选择课程01的学生s_id
INNER JOIN Score as c ON b.s_id = c.s_id AND c.c_id='02' # 过滤出选择 02课程的学生并且也选择了 课程01
)
1
2
3
4
5
6
2
3
4
5
6
# 07.学过01没学过02
- 学过编号为"01"但是没有学过编号为"02"的课程的同学的信息
-- [分析] 在上述语句中用and联结,注意不能直接将“=”换成“<>”
SELECT * FROM Student
WHERE s_id IN
(SELECT a.s_id FROM Student as a INNER JOIN Score as b ON a.s_id = b.s_id and b.c_id='01')
and s_id NOT IN
(SELECT a.s_id FROM Student as a INNER JOIN Score as c ON a.s_id = c.s_id and c.c_id='02')
1
2
3
4
5
6
2
3
4
5
6
# 08.没有学全所有课程的同学
- 查询没有学全所有课程的同学的信息
-- [分析]没学全所有课程的情况很多,如学0门,学1门,学2门。所以这里先筛选出学全所有课程的同学再取反,即没有学全所有课程的同学。
SELECT * FROM Student
WHERE s_id NOT IN
(
SELECT s_id FROM Score GROUP BY s_id HAVING COUNT(c_id) # 聚合统计所有同学学习的课程数量
= (select count(c_id) from Course) # 学习数量 等于 课程总数量
)
1
2
3
4
5
6
7
2
3
4
5
6
7
# 09.没学过"张三"课程学生
- 查询没学过"张三"老师讲授的任一门课程的学生姓名
SELECT s_name FROM Student
WHERE s_id NOT In (
SELECT s_id FROM Score WHERE c_id IN
(
# 找到 张三 老师教授的所有课程
SELECT c_id FROM Course WHERE t_id = (SELECT t_id FROM Teacher WHERE t_name='张三')
)
)
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
# 10.两门不及格课程同学
- 查询两门及其以上不及格课程的同学的学号,姓名及其平均成绩
SELECT a.s_id,a.s_name,avg(b.s_score)
FROM Student as a INNER JOIN Score AS b ON a.s_id=b.s_id and b.s_score < 60
GROUP BY a.s_id HAVING COUNT(b.s_score)>= 2;
1
2
3
2
3
# 11."01"课程分数小于60
- 检索"01"课程分数小于60,按分数降序排列的学生信息
-- [分析] 内联结+子查询筛选+排序
SELECT a.s_id,a.s_name,b.s_score,b.c_id
FROM Student as a INNER JOIN Score as b
ON a.s_id = b.s_id and b.c_id = 01 AND b.s_score <= 60 ORDER BY b.s_score DESC;
1
2
3
4
2
3
4
# 12 按平均成绩排序
- 按平均成绩从高到低显示所有学生的所有课程的成绩以及平均成绩(重要!)
select a.s_id,(select s_score from Score where s_id = a.s_id and c_id = '01') as 语文,
(select s_score from Score where s_id = a.s_id and c_id = '02') as 数学,
(select s_score from Score where s_id = a.s_id and c_id = '03') as 英语,
round(avg(s_score),2) as 平均分
from Score as a
group by a.s_id
order by 平均分 desc;
1
2
3
4
5
6
7
2
3
4
5
6
7
# 13.查询各科成绩最高分、最低分和平均分
- 查询各科成绩最高分、最低分和平均分
- 以如下形式显示:课程ID,课程name,最高分,最低分,平均分,及格率,中等率,优良率,
- 优秀率--及格为>=60,
- 中等为:70-80,
- 优良为:80-90,
- 优秀为:>=90(重要!)
-- [分析] 用到case语句,后面记得按课程号分组来显示全部结果
select a.c_id,a.c_name,max(b.s_score),min(b.s_score),avg(b.s_score),
round(100*(sum(case when b.s_score >= 60 then 1 else 0 end)/sum(case when b.s_score then 1 else 0 end)),2) as 及格率,
round(100*(sum(case when b.s_score between 70 and 80 then 1 else 0 end)/sum(case when b.s_score then 1 end)),2) as 中等率,
round(100*(sum(case when b.s_score between 80 and 90 then 1 else 0 end)/sum(case when b.s_score then 1 end)),2) as 优良率,
round(100*(sum(case when b.s_score >= 90 then 1 else 0 end)/sum(case when b.s_score then 1 end)),2) as 优秀率
from Course as a inner join Score as b on a.c_id = b.c_id
group by a.c_id,a.c_name;
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
# 14.学生的总成绩并进行排名
SELECT s_id, SUM(s_score) FROM Score GROUP BY s_id ORDER BY SUM(s_score) DESC
1
# 15.不同老师不同课程平均分
- 查询不同老师所教不同课程平均分从高到低显示
SELECT a.t_id,avg(b.s_score)
FROM Course as a INNER JOIN Score as b ON a.c_id=b.c_id
GROUP BY a.t_id ORDER BY avg(b.s_score) desc;
1
2
3
2
3
# 16.总成绩第2名到第3名
- 查询所有课程的总成绩第2名到第3名的学生信息及该课程成绩
SELECT a.s_id,SUM(b.s_score)
FROM Student as a INNER JOIN Score as b ON a.s_id=b.s_id
GROUP BY a.s_id ORDER BY SUM(b.s_score) DESC
LIMIT 2 OFFSET 1
1
2
3
4
2
3
4
# 17.各科成绩前三名的记录
- 查询各科成绩前三名的记录(重要!!!!!)
(select * from Score where c_id = '01' order by s_score desc limit 3)
UNION
(select * from Score where c_id = '02' order by s_score desc limit 3)
UNION
(select * from Score where c_id = '03' order by s_score desc limit 3);
1
2
3
4
5
2
3
4
5
# 18.每门课程被选修的学生数
-- [分析] 有点简单,写完甚至有点难以置信,还亲自去数了一遍。。。。。。
select c_id, count(s_id)
from Score
group by c_id;
1
2
3
4
2
3
4
# 19.只有两门课程学生
- 查询出只有两门课程的全部学生的学号和姓名
-- [分析] 内联结+筛选
select a.s_id,a.s_name
from student as a inner join score as b on a.s_id = b.s_id
group by a.s_id
having count(b.c_id) = 2;
1
2
3
4
5
2
3
4
5
# 20.查询男生、女生人数
# 方法1:
select s_sex,count(s_sex) as 人数
from Student
GROUP BY s_sex
# 方法2:
(select s_sex,count(s_sex) as 人数 from Student where s_sex = '男')
union
(select s_sex,count(s_sex) as 人数 from Student where s_sex = '女')
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
# 21.名字中含有"风"字的学生
SELECT * FROM Student WHERE s_name LIKE'%风%'
1
# 22.姓名性别相同的学生数量
- 查询同名同性学生名单,并统计同名人数(重要!!!!!)
-- [分析] 将表student定义两次,然后进行内联结,并给出判断条件
SELECT a.s_name,a.s_sex,COUNT(*)
FROM Student AS a INNER JOIN Student as b on
a.s_id <> b.s_id # 用户id不同
AND a.s_name = b.s_name # 名字和姓名都相同
and a.s_sex = b.s_sex
GROUP BY a.s_name,a.s_sex;
1
2
3
4
5
6
7
2
3
4
5
6
7
# 23.查询1990年出生的学生
-- [分析] 字符串模糊查询
SELECT *
FROM Student
WHERE s_birth like "1990%"
1
2
3
4
2
3
4
# 24.课程平均成绩排列
- 查询每门课程的平均成绩,结果按平均成绩降序排列,平均成绩相同时,按课程编号升序排列
-- [分析] 考察order by 语句的升降序及先后次序
SELECT c_id, AVG(s_score)
FROM Score
GROUP BY c_id
ORDER BY AVG(s_score) DESC,c_id ASC
1
2
3
4
5
2
3
4
5
# 25.平均成绩大于等于85学生
- 查询平均成绩大于等于85的所有学生的学号、姓名和平均成绩
SELECT a.s_id,a.s_name,AVG(b.s_score)
FROM Student as a INNER JOIN Score AS bON a.s_id = b.s_id
GROUP BY a.s_id,a.s_name
HAVING AVG(b.s_score) > 85
1
2
3
4
2
3
4
# 26.课程为数学且分数低于60
- 查询课程名称为"数学",且分数低于60的学生姓名和分数
SELECT a.s_name,b.s_score,b.c_id,c.c_name
FROM Student AS a INNER JOIN Score AS b ON a.s_id=b.s_id
INNER JOIN Course as c ON b.c_id = c.c_id AND c.c_name = '数学'
1
2
3
2
3
# 27.任一门成绩在70以上
- 查询任何一门课程成绩在70分以上的姓名、课程名称和分数;
SELECT a.s_name,b.s_score,c.c_name
FROM Student AS a INNER JOIN Score AS b ON a.s_id = b.s_id
INNER JOIN Course as c ON b.c_id = c.c_id
WHERE b.s_score >= 70
1
2
3
4
2
3
4
# 28.查询所有不及格学生
SELECT a.s_id,a.s_name,c.c_id,c.c_name,b.s_score
FROM Student AS a INNER JOIN Score AS b ON a.s_id = b.s_id
INNER JOIN Course as c ON b.c_id = c.c_id
WHERE b.s_score < 60
1
2
3
4
2
3
4
# 29.课程为01成绩在80分上
- 查询课程编号为01且课程成绩在80分以上的学生的学号和姓名
SELECT a.s_id,a.s_name,b.c_id,b.s_score
FROM Student as a INNER JOIN Score AS b ON a.s_id = b.s_id
WHERE b.c_id = '01' AND b.s_score >= 80
1
2
3
2
3
# 30.求每门课程的学生人数
SELECT a.c_name,COUNT(b.s_id)
FROM Course AS a INNER JOIN Score as b ON a.c_id = b.c_id GROUP BY a.c_name
1
2
2
# 31."张三"老师课程最高学生
- 查询选修"张三"老师所授课程的学生中,成绩最高的学生信息及其成绩
SELECT *
FROM Student AS a INNER JOIN Score as b ON a.s_id = b.s_id
INNER JOIN Course AS c ON c.c_id = b.c_id
INNER JOIN Teacher as d ON c.t_id = d.t_id
WHERE d.t_name = '张三'
ORDER BY b.s_score DESC LIMIT 1
1
2
3
4
5
6
2
3
4
5
6
# 32.不同课程成绩相同的学生
- 查询不同课程成绩相同的学生的学生编号、课程编号、学生成绩 (重要!!!!)
SELECT distinct b.s_id,b.c_id,b.s_score
FROM Score AS a, Score AS b
WHERE a.c_id !=b.c_id AND a.s_score = b.s_score
1
2
3
2
3
# 33.每门功成绩最好的前两名
- 查询每门功成绩最好的前两名
(select c_id,s_score from Score where c_id = '01' order by s_score desc limit 2)
UNION
(select c_id,s_score from Score where c_id = '02' order by s_score desc limit 2)
UNION
(select c_id,s_score from Score where c_id = '03' order by s_score desc limit 2)
1
2
3
4
5
2
3
4
5
# 34.选修学生超过5人
- 统计每门课程的学生选修人数(超过5人的课程才统计)。
- 要求输出
课程号和选修人数
,查询结果按人数降序排列,若人数相同,按课程号升序排列
SELECT c_id,COUNT(s_id)
FROM Score GROUP BY c_id
HAVING COUNT(s_id) >= 5
ORDER BY COUNT(s_id) DESC,c_id ASC
1
2
3
4
2
3
4
# 35.选修全部课程学生
- 查询选修了全部课程的学生信息
SELECT a.* ,COUNT(c_id)
FROM Student AS a INNER JOIN Score AS b on a.s_id = b.s_id
GROUP BY s_id
HAVING COUNT(b.c_id) = (SELECT COUNT(c_id) FROM Course)
1
2
3
4
2
3
4
# 36.计算学生年龄
- 查询各学生的年龄 按照出生日期来算,当前月日 < 出生年月的月日则,年龄减一
select s_birth,(DATE_FORMAT(NOW(),'%Y')-DATE_FORMAT(s_birth,'%Y') -
(case when DATE_FORMAT(NOW(),'%m%d')>DATE_FORMAT(s_birth,'%m%d') then 0 else 1 end)) as age
from Student;
1
2
3
2
3
# 37.下周过生日的学生
select * from Student where WEEK(DATE_FORMAT(NOW(),'%Y%m%d'))+1=WEEK(s_birth)
1
# 38.每门成绩大于80学生信息
SELECT * FROM Student WHERE s_id IN (
select s_id from Score group by s_id having min(s_score)>=80
)
1
2
3
2
3