`
一
环境
/*
Navicat Premium Data Transfer
Source Server : ssmbuild
Source Server Type : MySQL
Source Server Version : 50716
Source Host : localhost:3306
Source Schema : sqldemo
Target Server Type : MySQL
Target Server Version : 50716
File Encoding : 65001
Date: 17/03/2022 22:31:40
*/
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for Course
-- ----------------------------
DROP TABLE IF EXISTS `Course`;
CREATE TABLE `Course` (
`c_id` varchar(20) COLLATE utf8_bin NOT NULL,
`c_name` varchar(20) COLLATE utf8_bin NOT NULL DEFAULT '',
`t_id` varchar(20) COLLATE utf8_bin NOT NULL,
PRIMARY KEY (`c_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
-- ----------------------------
-- Records of Course
-- ----------------------------
BEGIN;
INSERT INTO `Course` VALUES ('01', '语文', '02');
INSERT INTO `Course` VALUES ('02', '数学', '01');
INSERT INTO `Course` VALUES ('03', '英语', '03');
COMMIT;
-- ----------------------------
-- Table structure for Score
-- ----------------------------
DROP TABLE IF EXISTS `Score`;
CREATE TABLE `Score` (
`s_id` varchar(20) COLLATE utf8_bin NOT NULL,
`c_id` varchar(20) COLLATE utf8_bin NOT NULL,
`s_score` int(3) DEFAULT NULL,
PRIMARY KEY (`s_id`,`c_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
-- ----------------------------
-- Records of Score
-- ----------------------------
BEGIN;
INSERT INTO `Score` VALUES ('01', '01', 80);
INSERT INTO `Score` VALUES ('01', '02', 90);
INSERT INTO `Score` VALUES ('01', '03', 99);
INSERT INTO `Score` VALUES ('02', '01', 70);
INSERT INTO `Score` VALUES ('02', '02', 60);
INSERT INTO `Score` VALUES ('02', '03', 80);
INSERT INTO `Score` VALUES ('03', '01', 80);
INSERT INTO `Score` VALUES ('03', '02', 80);
INSERT INTO `Score` VALUES ('03', '03', 80);
INSERT INTO `Score` VALUES ('04', '01', 50);
INSERT INTO `Score` VALUES ('04', '02', 30);
INSERT INTO `Score` VALUES ('04', '03', 20);
INSERT INTO `Score` VALUES ('05', '01', 76);
INSERT INTO `Score` VALUES ('05', '02', 87);
INSERT INTO `Score` VALUES ('06', '01', 31);
INSERT INTO `Score` VALUES ('06', '03', 34);
INSERT INTO `Score` VALUES ('07', '02', 89);
INSERT INTO `Score` VALUES ('07', '03', 98);
COMMIT;
-- ----------------------------
-- Table structure for Student
-- ----------------------------
DROP TABLE IF EXISTS `Student`;
CREATE TABLE `Student` (
`s_id` varchar(20) COLLATE utf8_bin NOT NULL,
`s_name` varchar(20) COLLATE utf8_bin NOT NULL DEFAULT '',
`s_birth` varchar(20) COLLATE utf8_bin NOT NULL DEFAULT '',
`s_sex` varchar(10) COLLATE utf8_bin NOT NULL DEFAULT '',
PRIMARY KEY (`s_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
-- ----------------------------
-- Records of Student
-- ----------------------------
BEGIN;
INSERT INTO `Student` VALUES ('01', '赵雷', '1990-01-01', '男');
INSERT INTO `Student` VALUES ('02', '钱电', '1990-12-21', '男');
INSERT INTO `Student` VALUES ('03', '孙风', '1990-05-20', '男');
INSERT INTO `Student` VALUES ('04', '李云', '1990-08-06', '男');
INSERT INTO `Student` VALUES ('05', '周梅', '1991-12-01', '女');
INSERT INTO `Student` VALUES ('06', '吴兰', '1992-03-01', '女');
INSERT INTO `Student` VALUES ('07', '郑竹', '1989-07-01', '女');
INSERT INTO `Student` VALUES ('08', '王菊', '1990-01-20', '女');
COMMIT;
-- ----------------------------
-- Table structure for Teacher
-- ----------------------------
DROP TABLE IF EXISTS `Teacher`;
CREATE TABLE `Teacher` (
`t_id` varchar(20) COLLATE utf8_bin NOT NULL,
`t_name` varchar(20) COLLATE utf8_bin NOT NULL DEFAULT '',
PRIMARY KEY (`t_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
-- ----------------------------
-- Records of Teacher
-- ----------------------------
BEGIN;
INSERT INTO `Teacher` VALUES ('01', '张三');
INSERT INTO `Teacher` VALUES ('02', '李四');
INSERT INTO `Teacher` VALUES ('03', '王五');
COMMIT;
SET FOREIGN_KEY_CHECKS = 1;
1、
-- 1.查询课程编号为“01”的课程比“02”的课程成绩高的所有学生的学号(重点)
-- 思路: 首先构建两个表a,b a 查询出全部学生课程01的成绩 b 查询出全部学生课程02的成绩
-- 然后两个表进行连接 条件就是 课程编号为“01”的课程比“02”的课程成绩高
select a.s_id "s_no" ,a.s_score "01",b.s_score "02" from (
select s_id,c_id,s_score from Score where c_id = '01' -- 首先先把课程为01的学生的成绩都找出来
) as a
inner JOIN (
select s_id,c_id,s_score from Score where c_id = '02' -- 把课程为02的学生的成绩都找出来
) as b on a.s_id = b.s_id
where a.s_score > b.s_score
-- 再查出相关的姓名
select a.s_id "s_no",c.s_name "姓名",a.s_score "01",b.s_score "02" from (
select s_id,c_id,s_score from Score where c_id = '01' -- 首先先把课程为01的学生的成绩都找出来
) as a
inner JOIN (
select s_id,c_id,s_score from Score where c_id = '02' -- 把课程为02的学生的成绩都找出来
) as b on a.s_id = b.s_id
INNER JOIN Student as c on c.s_id=a.s_id
where a.s_score > b.s_score
2、
-- 2、查询平均成绩大于60分的学生的学号和平均成绩(简单,第二道重点)
select s_id,avg(s_score) from Score
GROUP BY Score.s_id HAVING avg(s_score) > 60
3、
-- 3、查询所有学生的学号、姓名、选课数、总成绩
select a.s_id,a.s_name,COUNT(b.c_id),SUM(case when b.s_score is null then 0 else b.s_score end)
from Student as a
LEFT JOIN Score as b
on a.s_id = b.s_id
GROUP BY a.s_id,a.s_name
4、
-- 4、查询姓“猴”的老师的个数
select COUNT(t.t_name)
from Teacher as t where
t.t_name like '猴%'
5、
-- 查询没学过“张三”老师课的学生的学号、姓名
-- 方法1
select s_id,s_name from Student
where s_id not in
(
select s_id from Score
where c_id = (
select c_id
from Course where
t_id = (
select t_id
from Teacher
where t_name = '张三'
)
)
)
-- 方法2
select s_id,s_name
from Student
where s_id not in (
select s_id from Score as s
INNER JOIN Course as c on s.c_id =c.c_id
INNER JOIN Teacher as t on c.t_id = t.t_id
where t.t_name='张三'
)
6、
-- 6、查询学过“张三”老师所教的所有课的同学的学号、姓名 与题5类似
select s_id,s_name from Student where s_id in (
select s_id from Score
where c_id =
(
select c_id from Course
where t_id = (
select t_id from Teacher
where t_name = '张三'
)
)
)
7、
-- 7、查询学过编号为“01”的课程并且也学过编号为“02”的课程的学生的学号、姓名
select s_id,s_name from Student
where s_id in (
select a.s_id from
(select s_id from Score where c_id = '01') as a
INNER JOIN
(select s_id from Score where c_id = '02') as b
on a.s_id = b.s_id
)
8、
-- 8、查询课程编号为“02”的总成绩
select sum(s_score) from Score where c_id = '02'
9、
-- 9、查询所有课程成绩小于60分的学生的学号、姓名
select DISTINCT a.s_id,a.s_name from Student as a
LEFT JOIN Score as b on a.s_id = b.s_id
where b.s_score <'60'
select a.s_id,a.s_name from Student as a
where s_id in (
select s_id from Score where s_score < '60'
GROUP BY s_id
)
10、
-- 10.查询没有学全所有课的学生的学号、姓名
-- 错误解法 没有考虑全部都没有选课的同学
select b.s_id,a.s_name from Student as a right JOIN
(select s_id
from Score
GROUP BY s_id
HAVING count(c_id) < (select count(c_id) from Course ))
as b
on a.s_id = b.s_id
-- 正确解法
select st.s_id,st.s_name
from Student as st
LEFT JOIN Score as sc on st.s_id = sc.s_id
GROUP BY st.s_id HAVING count(DISTINCT sc.c_id) < (SELECT COUNT(DISTINCT c_id) from Course)
11、
-- 11、查询至少有一门课与学号为“01”的学生所学课程相同的学生的学号和姓名
select b.s_id,a.s_name from Student as a
RIGHT JOIN
(select DISTINCT s_id from Score where c_id in
(
select c_id from Score where s_id = '01'
))
as b
on a.s_id = b.s_id
where a.s_id != '01'
select s_id,s_name from Student where s_id in (
select DISTINCT s_id from Score where c_id in
(
select c_id from Score where s_id = '01'
) and s_id != '01')
12、
-- 12.查询和“01”号同学所学课程完全相同的其他同学的学号
select s_id from Student
where s_id in (
select s_id from Score
where s_id != '01'
GROUP BY s_id having count(DISTINCT c_id) = (select count(DISTINCT c_id) from Score where s_id = '01')
)
and s_id not in (
select c_id from
Score where c_id not in
(select c_id from Score where s_id = '01'
)
)
13、
-- 13、查询没学过"张三"老师讲授的任一门课程的学生姓名 和47题一样
select s_id,s_name from Student
where s_id not in (
select s_id from Score where c_id = (
select c_id from Course where t_id =
(select t_id from Teacher where t_name = '张三')
)
)
14、
15、
-- 15、查询两门及其以上不及格课程的同学的学号,姓名及其平均成绩
select a.s_id,a.s_name,b.s_score from Student as a
INNER JOIN (
select s_id,avg(s_score) as s_score from Score where s_score <'60'
GROUP BY s_id HAVING count(c_id) >= 2
)
as b
on a.s_id = b.s_id
select a.s_id, a.s_name,avg(s_score)
from Student as a
INNER JOIN Score as b
on a.s_id = b.s_id
where a.s_id in (
select s_id as s_score from Score where s_score <'60'
GROUP BY s_id HAVING count(DISTINCT c_id) >= 2
)
GROUP BY s_id , s_name
16、
-- 16、检索"01"课程分数小于60,按分数降序排列的学生信息
select * from Student as a
RIGHT JOIN (
select s_id from Score where c_id = '01' and s_score < '60'
ORDER BY s_score DESC
)as b
on a.s_id = b.s_id
select t.*,s.c_id,s.s_score from Student as t
INNER JOIN Score as s on t.s_id = s.s_id
where s.c_id ='01' and s.s_score < 60
ORDER BY s.s_score desc
17、
-- 17、按平均成绩从高到低显示所有学生的所有课程的成绩以及平均成绩
select * from Score as a
LEFT JOIN
(select s_id,avg(s_score) as avg_s_score from Score
GROUP BY s_id)
as b
on a.s_id = b.s_id
order BY b.avg_s_score desc
-- 方式二 更好的
select s_id "学号",
max(CASE WHEN c_id = '01' THEN s_score ELSE 0 END) "语文",
max(CASE WHEN c_id = '02' THEN s_score ELSE 0 END) "数学",
max(CASE WHEN c_id = '03' THEN s_score ELSE 0 END) "英语",
avg(s_score)
from Score
GROUP BY s_id
ORDER BY avg(s_score) DESC
18、
-- 18.查询各科成绩最高分、最低分和平均分:以如下形式显示:课程ID,课程name,
-- 最高分,最低分,平均分,及格率,中等率,优良率,优秀率
select s.c_id,c_name,
max(s.s_score) "最高分",
min(s.s_score) "最低分" ,
avg(s.s_score) "平均分",
sum(case when s.s_score >= 60 then 1 else 0 end)/count(s_id) "及格",
sum(case when s.s_score >= 70 and s.s_score <80 then 1 else 0 end)/count(s_id) "中等",
sum(case when s.s_score >= 80 and s.s_score <90 then 1 else 0 end)/count(s_id) "优良",
sum(case when s.s_score >= 90 then 1 else 0 end)/count(s_id) "优秀"
from Score as s
INNER JOIN Course as c
on s.c_id = c.c_id
GROUP BY c_id
19、
-- 19、按各科成绩进行排序,并显示排名
select s_id,c_id,s_score,row_number() over (ORDER BY s_score desc)
from Score
20、
-- 20、查询学生的总成绩并进行排名
select s_id,sum(s_score) from Score
GROUP BY s_id
ORDER BY sum(s_score)desc
21、
-- 21 、查询不同老师所教不同课程平均分从高到低显示
-- 自 以课程为主体 求平均分
select t_name,su.c_name,avg_score from Teacher as t
LEFT JOIN (
select c.c_id,t_id,c_name,avg(s_score) as avg_score from Score as s,Course as c where s.c_id = c.c_id
GROUP BY c.c_id,c_name
) as su
on su.t_id = t.t_id
ORDER BY avg_score desc
-- 以老师为主体 老师教的课程多的情况 一个老师教多门课
select t.t_id,t.t_name,avg(sc.s_score) as avg_score
from Score as sc
INNER JOIN Course as c on sc.c_id = c.c_id
INNER JOIN Teacher as t on c.t_id = t.t_id
GROUP BY t.t_id,t.t_name
ORDER BY avg_score desc
22、
-- 22、查询所有课程的成绩第2名到第3名的学生信息及该课程成绩
select *
from (
select st.s_id,st.s_name,st.s_birth,st.s_sex,c_id,s_core,row_number() over(partition by c_id ORDER BY s_core desc) m
from Score sc INNER JOIN Student st on sc.c_id = st.s_id
) a
where m in (2,3)
23、
-- 23、使用分段[100-85],[85-70],[70-60],[<60]来统计各科成绩,分别统计各分数段人数:课程ID和课程名称
select a.c_id,c_name,t as '[<60]',y as '[70-60]',u as '[85-70]', i as '[100-85]' from Course as a
INNER JOIN
(
select c_id,
sum(CASE WHEN s_score<=60 THEN 1 ELSE 0 END) as t ,
sum(CASE WHEN s_score>60 and s_score <= 70 THEN 1 ELSE 0 END) as y ,
sum(CASE WHEN s_score>70 and s_score <=85 THEN 1 ELSE 0 END) as u ,
sum(CASE WHEN s_score>85 and s_score <=100 THEN 1 ELSE 0 END) as i
from Score
GROUP BY c_id
) as b
on a.c_id = b.c_id
-- Up答案
select c.c_id,c.c_name,
sum(CASE WHEN sc.s_score<=60 THEN 1 ELSE 0 END) as "[<60]",
sum(CASE WHEN sc.s_score>60 and sc.s_score <= 70 THEN 1 ELSE 0 END) as "[70-60]",
sum(CASE WHEN sc.s_score>70 and sc.s_score <=85 THEN 1 ELSE 0 END) as "[85-70]" ,
sum(CASE WHEN sc.s_score>85 and sc.s_score <=100 THEN 1 ELSE 0 END) as "[100-85]"
from Score as sc
INNER JOIN Course as c on sc.c_id = c.c_id
GROUP BY c.c_id ,c.c_name
24、
-- 24、查询学生平均成绩及其名次
select s_id ,avg(s_score),row_number () over (ORDER BY avg(s_score) desc)
from Score
GROUP BY s_id
25、排列
-- 25、查询各科成绩前三名的记录(不考虑成绩并列情况)
26、
-- 26、查询每门课程被选修的学生数
select sc.c_id,c.c_name,count(DISTINCT sc.s_id) from Score as sc
INNER JOIN Course as c
on sc.c_id = c.c_id
GROUP BY sc.c_id,c.c_name
27、
-- 27、 查询出只有两门课程的全部学生的学号和姓名
-- 方式1
select st.s_id,st.s_name from Student as st
INNER JOIN Score as sc
on st.s_id = sc.s_id
GROUP BY st.s_id HAVING count(DISTINCT sc.c_id) = '2'
-- 方式2 in的方式效率会低
select s_id,s_name from Student
where s_id in(
select s_id FROM Score
GROUP BY s_id HAVING count(DISTINCT c_id) = 2
)
28、
-- 28、查询男生、女生人数
select sum(CASE WHEN s_sex = '男' THEN 1 ELSE 0 END) as '男生数量' ,
sum(CASE WHEN s_sex = '女' THEN 1 ELSE 0 END) as '女生数量'
from Student
select s_sex,count(DISTINCT s_id) from Student
GROUP BY s_sex
29、
-- 29 查询名字中含有"风"字的学生信息
select * from Student
where s_name like '%风%'
30、
31、
-- 31、查询1990年出生的学生名单
select * from Student
where YEAR(s_birth) = '1990'
32、
-- 32、查询平均成绩大于等于85的所有学生的学号、姓名和平均成绩
select st.s_id,st.s_name,avg(sc.s_score) from Student as st
INNER JOIN Score as sc
on st.s_id = sc.s_id
GROUP BY s_id HAVING avg(sc.s_score) >= 85
33、
-- 33、查询每门课程的平均成绩,结果按平均成绩升序排序,平均成绩相同时,按课程号降序排列
select s.c_id,c.c_name,avg(s.s_score) from Score as s
INNER JOIN Course as c on s.c_id = c.c_id
GROUP BY s.c_id
ORDER BY avg(s_score) asc , s.c_id desc
34、
-- 34、查询课程名称为"数学",且分数低于60的学生姓名和分数
select a.s_id,a.s_name,b.s_score from Student as a
INNER JOIN
(
select s_id,s_score from Score where
c_id = (
select c_id from Course where c_name = '数学'
) and s_score < 60
)
as b on a.s_id = b.s_id
-- up答案
select s.s_id,s.s_score,st.s_name
from Score as s
INNER JOIN Course as c on s.c_id = c.c_id
INNER JOIN Student as st on s.s_id = st.s_id
where c.c_name = "数学" and s.s_score < 60
35、
-- 35、查询所有学生的课程及分数情况(重点)
-- 需要注意的是 在分组的时候 case when 只会去匹配的时候只会返回到第一条 因为其他的都是不满足条件的
-- 可以使用一个max去返回 因为最大的那个有值
select sd.s_id ,sd.s_name,
max(case when c.c_name = '语文' then s.s_score else null end) as '语文',
max(case when c.c_name = '数学' then s.s_score else null end) as '数学',
max(case when c.c_name = '英语' then s.s_score else null end) as '英语'
from Score as s
INNER JOIN Course as c on s.c_id = c.c_id
INNER JOIN Student as sd on s.s_id = sd.s_id
GROUP BY sd.s_id ,sd.s_name
36、
-- 36、查询任何一门课程成绩在70分以上的姓名、课程名称和分数
select st.s_name,sc.c_id,co.c_name,sc.s_score from Student as st
INNER JOIN Score as sc on st.s_id = sc.s_id
INNER JOIN Course as co on sc.c_id = co.c_id
where sc.s_score > 70
select st.s_id,st.s_name,
max(case when co.c_name = '语文' then sc.s_score else null end) as '语文',
max(case when co.c_name = '数学' then sc.s_score else null end) as '数学',
max(case when co.c_name = '英语' then sc.s_score else null end) as '英语'
from Student as st
INNER JOIN Score as sc on st.s_id = sc.s_id
INNER JOIN Course as co on sc.c_id = co.c_id
where sc.s_score > 70
GROUP BY st.s_id,st.s_name
37、
-- 37、查询不及格的课程并按课程号从大到小排列
select st.s_id,st.s_name,sc.c_id,co.c_name,sc.s_score FROM Student as st
INNER JOIN(
select * from Score where s_score < 60
) as sc
on st.s_id = sc.s_id
INNER JOIN Course as co
on sc.c_id = co.c_id
order by sc.c_id desc
38、
-- 38、查询课程编号为03且课程成绩在80分以上的学生的学号和姓名
select st.s_id,st.s_name from Student as st
where s_id in (
select s_id from Score where c_id = 03 and s_score > 80
)
39、
-- 39、求每门课程的学生人数
select c.c_id,c.c_name, count(DISTINCT s_id) from Score as s
INNER JOIN Course as c on c.c_id = s.c_id
GROUP BY c.c_id,c.c_name
40、
-- 40、查询选修“张三”老师所授课程的学生中成绩最高的学生姓名及其成绩
select st.s_name,te.t_name,sc.s_score from Student as st
INNER JOIN Score as sc on st.s_id = sc.s_id
INNER JOIN Course as co on sc.c_id = co.c_id
INNER JOIN Teacher as te on co.t_id = te.t_id
where te.t_name = '张三'
ORDER BY sc.s_score DESC LIMIT 0,1
41、
-- 41.查询不同课程成绩相同的学生的学生编号、课程编号、学生成绩
select s_id from (
select b.s_id,b.s_score from Score as b
INNER JOIN (
select s_id from Score
GROUP BY s_id HAVING count(DISTINCT c_id) > 1
) as c on b.s_id = c.s_id
GROUP BY b.s_id, b.s_score
) as a
GROUP BY s_id HAVING count(s_id) = 1
42、排列
-- 42、查询每门功成绩最好的前两名
43、
-- 43、统计每门课程的学生选修人数(超过5人的课程才统计)。
-- 要求输出课程号和选修人数,查询结果按人数降序排列,若人数相同,按课程号升序排列
select c_id,case when count(s_score) > 5 then count(s_score) else null end
as coun from Score
GROUP BY c_id
ORDER BY coun DESC,c_id desc
select c_id,count(DISTINCT s_id) as cnt from Score
GROUP BY c_id HAVING cnt > 5
ORDER BY cnt desc,c_id desc
44、
-- 44、检索至少选修两门课程的学生学号
select st.s_id,st.s_name,count(sc.s_score) from Student as st
INNER JOIN Score as sc
on st.s_id = sc.s_id
GROUP BY sc.s_id HAVING count(sc.s_score) >= 2
select s_id,count(DISTINCT c_id) as cnt FROM Score
GROUP BY s_id HAVING cnt >=2
45、
-- 45、 查询选修了全部课程的学生信息
select * from Student
where s_id in(
select s_id from Score
GROUP BY s_id HAVING count(s_score) = (select count(c_id) from Course)
)
46、
-- 46、查询各学生的年龄
-- DATEDIFF函数:返回两个日期之间的天数 参数1 减去参数2
-- round 函数 取整 会进位 向上取整
-- 如果不进位可以使用 floor函数 向下取整
select s_id,s_birth,ROUND(DATEDIFF('2022-3.16',s_birth) / 365)
from Student
47、
-- 47、查询没学过“张三”老师讲授的任一门课程的学生姓名
select * from Student where s_id not in (
select s_id from Score as sc
INNER JOIN Course as co on sc.c_id = co.c_id
INNER JOIN Teacher as te on co.t_id = te.t_id
where te.t_name = '张三')
48、
-- 48、查询本月过生日的同学
select * from Student
WHERE MONTH(s_birth) = month(NOW())
49、
-- 49、查询下月过生日的学生
50
二
环境
/*
Navicat Premium Data Transfer
Source Server : ssmbuild
Source Server Type : MySQL
Source Server Version : 50716
Source Host : localhost:3306
Source Schema : sqldemo1
Target Server Type : MySQL
Target Server Version : 50716
File Encoding : 65001
Date: 17/03/2022 22:20:30
*/
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for course
-- ----------------------------
DROP TABLE IF EXISTS `course`;
CREATE TABLE `course` (
`Cno` varchar(10) NOT NULL,
`Cname` varchar(10) DEFAULT NULL,
`Tno` varchar(10) DEFAULT NULL,
PRIMARY KEY (`Cno`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of course
-- ----------------------------
BEGIN;
INSERT INTO `course` VALUES ('01', '语文', '02');
INSERT INTO `course` VALUES ('02', '数学', '01');
INSERT INTO `course` VALUES ('03', '英语', '03');
COMMIT;
-- ----------------------------
-- Table structure for sc
-- ----------------------------
DROP TABLE IF EXISTS `sc`;
CREATE TABLE `sc` (
`Sno` varchar(10) NOT NULL,
`Cno` varchar(10) NOT NULL,
`score` decimal(18,1) DEFAULT NULL,
PRIMARY KEY (`Sno`,`Cno`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of sc
-- ----------------------------
BEGIN;
INSERT INTO `sc` VALUES ('01', '01', 80.0);
INSERT INTO `sc` VALUES ('01', '02', 90.0);
INSERT INTO `sc` VALUES ('01', '03', 99.0);
INSERT INTO `sc` VALUES ('02', '01', 70.0);
INSERT INTO `sc` VALUES ('02', '02', 60.0);
INSERT INTO `sc` VALUES ('02', '03', 80.0);
INSERT INTO `sc` VALUES ('03', '01', 80.0);
INSERT INTO `sc` VALUES ('03', '02', 80.0);
INSERT INTO `sc` VALUES ('03', '03', 80.0);
INSERT INTO `sc` VALUES ('04', '01', 50.0);
INSERT INTO `sc` VALUES ('04', '02', 30.0);
INSERT INTO `sc` VALUES ('04', '03', 20.0);
INSERT INTO `sc` VALUES ('05', '01', 76.0);
INSERT INTO `sc` VALUES ('05', '02', 87.0);
INSERT INTO `sc` VALUES ('06', '01', 31.0);
INSERT INTO `sc` VALUES ('06', '03', 34.0);
INSERT INTO `sc` VALUES ('07', '02', 89.0);
INSERT INTO `sc` VALUES ('07', '03', 98.0);
COMMIT;
-- ----------------------------
-- Table structure for student
-- ----------------------------
DROP TABLE IF EXISTS `student`;
CREATE TABLE `student` (
`Sno` varchar(10) NOT NULL,
`Sname` varchar(10) DEFAULT NULL,
`Sage` date DEFAULT NULL,
`Ssex` varchar(10) DEFAULT NULL,
PRIMARY KEY (`Sno`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of student
-- ----------------------------
BEGIN;
INSERT INTO `student` VALUES ('01', '赵雷', '1990-01-01', '男');
INSERT INTO `student` VALUES ('02', '钱电', '1990-12-21', '男');
INSERT INTO `student` VALUES ('03', '孙风', '1990-05-20', '男');
INSERT INTO `student` VALUES ('04', '李云', '1990-08-06', '男');
INSERT INTO `student` VALUES ('05', '周梅', '1991-12-01', '女');
INSERT INTO `student` VALUES ('06', '吴兰', '1992-03-01', '女');
INSERT INTO `student` VALUES ('07', '郑竹', '1989-07-01', '女');
INSERT INTO `student` VALUES ('08', '王菊', '1990-01-20', '女');
INSERT INTO `student` VALUES ('09', '王菊', '2022-03-16', '女');
COMMIT;
-- ----------------------------
-- Table structure for teacher
-- ----------------------------
DROP TABLE IF EXISTS `teacher`;
CREATE TABLE `teacher` (
`Tno` varchar(10) NOT NULL,
`Tname` varchar(10) DEFAULT NULL,
PRIMARY KEY (`Tno`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of teacher
-- ----------------------------
BEGIN;
INSERT INTO `teacher` VALUES ('01', '张三');
INSERT INTO `teacher` VALUES ('02', '李四');
INSERT INTO `teacher` VALUES ('03', '王五');
COMMIT;
SET FOREIGN_KEY_CHECKS = 1;
1、Like
-- 查询「李」姓老师的数量 【Like】
select count(Tno) from teacher where Tname like "李%"
2、
-- 2. 查询名字中含有「风」字的学生信息【Like】
select * from student
where Sname like "%风%"
3、聚合函数
-- 3. 查询男生、女生人数【聚合函数】
select Ssex,count(*) from student
GROUP BY Ssex
4、
-- 4. 查询课程编号为02的总成绩【聚合函数】
select sum(score) from sc
where Cno = '02'
select cno, sum(score) from sc
group by cno having cno='02';
5、
-- 5. 查询每门课程的平均成绩,结果按平均成绩降序排列,
-- 平均成绩相同时,按课程编号升序排列【聚合函数】
select cno,avg(score) from sc
GROUP BY cno
order by avg(score) desc,cno asc
6、
-- 6. 求每门课程的学生人数 【聚合函数】
select cno,count(sno) from sc
GROUP BY Cno
7、
-- 7. 统计每门课程的学生选修人数(超过 5 人的课程才统计)【聚合函数】
select cno,count(score) from sc
group by Cno HAVING count(score) > 5
order by count(score) desc,cno asc
8、
-- 8. 检索至少选修两门课程的学生学号 【聚合函数】
select sno,count(score) from sc
GROUP BY sno HAVING count(score) >= 2
9、子查询
-- 9. 查询在 SC 表存在成绩的学生信息【子查询】
select * from student
where sno in (
select sno from sc
)
10、
-- 10. 查询不存在" 01 "课程但存在" 02 "课程的情况【子查询】
select * from sc
where sno not in (select sno from sc where cno =01)
and sno in (select sno from sc where cno=02);
11、
-- 11. 查询同时存在" 01 "课程和" 02 "课程的情况【子查询】
select * from sc where
sno in (
select sno from sc where cno = '01'
) and sno in (select sno from sc where cno = '02')
12、
-- 12. 查询出只选修两门课程的学生学号和姓名【子查询】
select Sno,Sname from student
where sno in(
select sno from sc
group by sno HAVING count(cno) = 2
)
13、
-- 13. 查询没有学全所有课程的同学的信息 【子查询】
select * from student
where sno not in (
select sno from sc
GROUP BY sno HAVING count(cno) = (
select count(Cno) from course
)
)
-- 错误答案 因为sc没有 08号学生
select * from student
where sno in (
select sno from sc
GROUP BY sno HAVING count(cno) < (
select count(Cno) from course
)
)
14、
-- 14. 查询选修了全部课程的学生信息【子查询】
select * from student
where sno in (
select sno from sc
GROUP BY Sno having count(cno) = (select count(cno) from course)
)
15、
-- 15. 查询所有课程成绩均小于60分的学号、姓名【子查询】
select * from student
where sno not in (
select sno from sc
where score >= 60
) and sno in (select DISTINCT sno FROM sc)
16、
-- 16. 查询课程编号为 01 且课程成绩在 80 分以上的学生的学号和姓名【子查询】
select sno, sname from student
where sno in (select sno from sc where cno='01' and score>80);
17、
-- 17. 查询学过「张三」老师授课的同学的信息 【子查询】
select * from student
where sno in (
select sno from sc
where cno in (
select cno from course where cno = (
select tno from teacher where Tname = '张三'
)
)
)
18、
-- 18. 查询没学过"张三"老师讲授的任一门课程的学生姓名 【子查询】
select * from student where sno not in (
select sno from sc where cno in (
select course.cno from course,teacher
where course.Tno = teacher.Tno and teacher.Tname = '张三'
))
select * from student where sno not in (
select sc.sno from sc,course,teacher
where sc.Cno = course.Cno and teacher.Tno = course.Tno and teacher.Tname = '张三'
)
19、
-- 19. 查询至少有一门课与学号为" 01 "的同学所学相同的同学的信息 【子查询】
select * from student where sno in (
select sno from sc where cno in (
select cno from sc where sno = 01
) and sno != '01'
GROUP BY sno
)
20、
-- 20. 查询和" 01 "号的同学学习的课程完全相同的其他同学的信息【子查询】
select * from student where sno in (
select sno from sc
where sno != 01
GROUP BY sno HAVING count(Cno) = (select count(cno) from sc where sno = 01)
)
and sno not in (
select sno from sc
where Cno not in (select cno from sc where sno = 01)
)
21、
-- 21. 查询不同课程成绩相同的学生的学生编号、课程编号、学生成绩 【子查询】
select * from sc where sno in
(select sno from sc group by sno
having min(score)=max(score) and count(*)>1);
22、联表查询
-- 22. 检索" 01 "课程分数小于 60,按分数降序排列的学生信息【inner join】
select b.*, a.score
from sc as a inner join student as b on a.sno=b.sno
where a.cno='01' and a.score<60 order by a.score desc;
select a.*,b.score from student as a
INNER JOIN (
select sno,score from sc where cno = 01 and score < 60
) as b on a.sno = b.sno
23、
-- 23. 查询不及格的课程及学生名,学号,按课程号从大到小排列【inner join】
select st.Sno,st.Sname,sc.cno,sc.score from student as st
INNER JOIN sc
on st.sno = sc.sno
where sc.score < 60
order by cno desc
24、
-- 24. 查询课程名称为「数学」,且分数低于 60 的学生姓名和分数 【inner join】
select st.Sname,c.Cname,sc.score from student as st
INNER JOIN sc on st.sno = sc.sno
INNER JOIN course as c on sc.cno = c.Cno
where c.Cname = '数学' and sc.score < 60
select b.sname, a.score
from sc as a inner join student as b on a.sno=b.sno
where a.score<60 and a.cno =(select cno from course where cname='数学');
25、
-- 25. 查询平均成绩大于等于 85 的所有学生的学号、姓名和平均成绩 【inner join】
select st.Sno,st.Sname,avg(score) from student as st
INNER JOIN sc on st.sno = sc.sno
group by sno HAVING avg(score) >= 85
26、
-- 26. 查询不同老师所教不同课程平均分从高到低显示【inner join】
select b.tno, a.cno, avg(a.score)
from sc as a inner join course as b on a.cno=b.cno
group by a.cno order by avg(a.score) desc;
27、
-- 27. 查询平均成绩大于等于 60 分的同学的学生编号和学生姓名和平均成绩【inner join】
select st.Sno,st.Sname,avg(score) from student as st
INNER JOIN sc on st.sno = sc.Sno
group by sno HAVING avg(sc.score) >= 60
28、
-- 28.查询两门及其以上不及格课程的同学的学号,姓名及其平均成绩【inner join】
select st.Sno,st.Sname,avg(sc.score),count(sc.score) from student as st
INNER JOIN sc on st.sno = sc.sno
where sc.score < 60
GROUP BY sno HAVING count(score) >=2
29、
-- 29. 查询同名同性学生名单,并统计同名同性人数【inner join】
select a.*, b.student_number
from student as a inner join
(select sname, ssex, count(*) as student_number from student
group by sname, ssex having count(*)>1) as b
on a.sname=b.sname and a.ssex=b.ssex;
30、
-- 30. 查询所有学生的课程及分数情况(存在学生没成绩,没选课的情况)【outer join】
select a.sno, a.sname, b.cno, b.score
from student as a left join sc as b
on a.sno=b.sno;
31、
-- 31. 查询所有同学的学生编号、学生姓名、选课总数、所有课程的总成绩。
-- (没成绩的显示为 null )【outer join】
select st.Sno,st.Sname,count(DISTINCT cno),sum(score) from student as st
LEFT JOIN sc on st.sno = sc.sno
GROUP BY sno
32、
-- 32. 查询存在" 01 "课程但可能不存在" 02 "课程的情况(不存在时显示为 null )【outer join】
select a.*, b.cno, b.score from
(select * from sc where cno='01') as a
left join (select * from sc where cno='02') as b
on a.sno=b.sno;
33、
-- 33. 查询任何一门课程成绩在 70 分以上的姓名、课程名称和分数【三表联结】
select st.Sname,co.Cname,sc.score from student as st
INNER JOIN sc on st.sno = sc.sno
INNER JOIN course as co on sc.cno = co.cno
where sc.score > 70
34、
-- 34. 查询" 01 "课程比" 02 "课程成绩高的学生的信息及课程分数【三表联结】
select a.*,b.score from student as a
INNER JOIN (
select * from sc where cno = 01
) as b on a.sno = b.sno
INNER JOIN (
select * from sc where cno = 02
) as c on b.sno = c.sno
where b.score > c.score
35、limit
-- 35. 成绩不重复,查询选修「张三」老师所授课程的学生中,
-- 成绩最高的学生信息及其成绩【limit】
select st.*,g.score from student as st
INNER JOIN
(
select * from sc where
sc.Cno = (
select c.cno from course as c
INNER JOIN
(select tno from teacher where tname = '张三') as t
on c.tno = t.Tno
)
ORDER BY score desc
limit 0,1
) as g on st.sno = g.sno
select student.*, sc.score
from sc, course, teacher,student
where teacher.tname='张三' and course.tno=teacher.tno and
course.cno=sc.cno and student.sno=sc.sno
order by sc.score desc limit 1;
36、
-- 36. 成绩有重复的情况下,查询选修「张三」老师所授课程的学生中,成绩最高的学生信息及其成绩【limit】
select a.* from
(select student.*, sc.cno, sc.score from student, sc where student.sno=sc.sno) as a
inner join
(select cno, score from sc where cno=(select cno from course, teacher where teacher.tname='张三'
and course.tno=teacher.tno )order by score desc limit 1) as b
on a.cno=b.cno and a.score=b.score;
37、窗口函数
-- 37. 按各科成绩进行排序,并显示排名,Score 重复时保留名次空缺【窗口函数】
select *, rank() over (partition by cno order by score desc) as ranking
from sc;
38、
-- 38. 按各科成绩进行排序,并显示排名,Score 重复时合并名次【窗口函数】
39、
-- 39. 查询学生的总成绩,并进行排名,总分重复时保留名次空缺【窗口函数】
40、
-- 40. 查询学生的总成绩,并进行排名,总分重复时不保留名次空缺【窗口函数】
41、
42、
43、
44、case
-- 44.按平均成绩从高到低显示所有学生的所有课程的成绩以及平均成绩【case】
select sc.sno,
max(case when course.Cname = '语文'then sc.score else 0 end) as "语文",
max(case when course.Cname = '数学'then sc.score else 0 end) as "数学",
max(case when course.Cname = '英语'then sc.score else 0 end) as "英语",
avg(sc.score)
from sc
INNER JOIN course
on sc.cno = course.Cno
GROUP BY sc.Sno
select b.sno, a.avg_score, a.01, a.02, a.03 from
(select sno, avg(score) as avg_score,
max(case when cno='01' then score else null end) as '01',
max(case when cno='02' then score else null end) as '02',
max(case when cno='03' then score else null end) as '03'
from sc group by sno) as a
right join student as b on a.sno=b.sno;
45、
-- 45. 使用分段[100-85],[85-70],[70-60],[<60]来统计各科成绩,
-- 分别统计各分数段人数:课程ID和课程名称【case】
select c.Cname,sc.cno ,
sum(case when sc.score > 85 and sc.score <= 100 then 1 else 0 end) as '[100-85)',
sum(case when sc.score > 70 and sc.score <= 85 then 1 else 0 end) as '[85-70)',
sum(case when sc.score > 60 and sc.score <= 70 then 1 else 0 end) as '[70-60)',
sum(case when sc.score <= 60 then 1 else 0 end) as '[<60)'
from course as c
INNER JOIN sc on c.cno = sc.cno
GROUP BY cno
46、
-- 46. 查询各科成绩最高分、最低分和平均分:以如下形式显示:
-- 课程 ID ,课程 name ,最高分,最低分,平均分,及格率,中等率,优良率,优秀率。
-- 及格为>=60,中等为:70-80,优良为:80-90,优秀为:>=90 【case】
select a.cno '课程ID', b.cname '课程name', max(a.score) '最高分', min(a.score) '最低分', avg(a.score) '平均分',
sum(case when a.score>=60 then 1 else 0 end)/count(a.score) '及格率',
sum(case when a.score>=70 and a.score<80 then 1 else 0 end)/count(a.score) '中等率',
sum(case when a.score>=80 and a.score<90 then 1 else 0 end)/count(a.score) '优良率',
sum(case when a.score>=90 then 1 else 0 end)/count(a.score) '优秀率'
from sc a inner join course b on a.cno=b.cno
group by a.cno;
47、
-- 47. 统计各科成绩各分数段人数:
-- 课程编号,课程名称,[100-85],[85-70],[70-60],[60-0] 及所占百分比【case】
select a.cno, b.cname,
sum(case when a.score>=85 then 1 else 0 end) as '[100-85]人数',
sum(case when a.score>=70 and a.score<85 then 1 else 0 end) as '[85-70]人数',
sum(case when a.score>=60 and a.score<70 then 1 else 0 end) as '[70-60]人数',
sum(case when a.score<60 then 1 else 0 end) as '[60-0]人数',
sum(case when a.score>=85 then 1 else 0 end)/count(a.sno) as '[100-85]百分比',
sum(case when a.score>=70 and a.score<85 then 1 else 0 end)/count(a.sno) as '[85-70]百分比',
sum(case when a.score>=60 and a.score<70 then 1 else 0 end)/count(a.sno) as '[70-60]百分比',
sum(case when a.score<60 then 1 else 0 end)/count(a.sno) as '[60-0]百分比'
from sc as a inner join course as b on a.cno=b.cno
group by a.cno;
48、时间函数
-- 48. 查询各学生的年龄,只按年份来算【时间函数】
-- 思路:year函数分别求出current_date和sage的年,相减即可
select sno, sname,
year(current_date())-year(sage) as age
from student;
49、
-- 49. 按照出生日期来算,当前月日 < 出生年月的月日则,年龄减一【时间函数】
-- 思路:使用timestampdiff()求差,将时间戳设置为年即可
Select sno, sname,
timestampdiff(year, sage, current_date()) as age
from student;
50、
-- 50. 查询本月过生日的学生【时间函数】
-- 思路:month函数分别求出current_date和sage的月份,相同即可
select sno, sname, sage from student
where month(sage)=month(current_date());
51、
-- 51. 查询下月过生日的学生
-- 思路参见50
select sno, sname, sage from student
where month(sage)=month(current_date())+1;
52、
-- 52. 查询本周过生日的学生
/* 思路:1.replace将生日中的年换为今天的年,计算同学的生日在本年是第几周;
2.求出今天是本年的第几周
3.若相等,则符合条件
注意:这种方法存在问题,1月第一周和12月最后一周可能跨年,倒置结果出错。欢迎提供更好的方案。*/
select sno, sname, sage from student
where week(replace(sage, year(sage), year(current_date())), 1) = week(current_date(),1);
53、
-- 53. 查询下周过生日的学生
-- 思路和存在问题参见52
select sno, sname, sage from student
where week(replace(sage, year(sage), year(current_date())), 1) = week(current_date(),1)+1;