MySQL 练习50题
概述
学习的精髓 = 理论+实操+总结,所有题都亲手敲一遍才会牢记。
下面是我自己写的答案,有些不会写只能空着,以后再补。(建表的SQL语句在文章最后)
1、表结构
2、案例答案
-- 1、查询"01"课程比"02"课程成绩高的学生的信息及课程分数
SELECT
stu.*,
s1.s_score as 01_score,
s2.s_score as 02_score
FROM
Student as stu
left JOIN Score s1 on stu.s_id = s1.s_id
AND s1.c_id = \'01\'
left JOIN Score s2 on stu.s_id = s2.s_id
AND s2.c_id = \'02\'
or s2.c_id = NULL
where
s1.s_score > s2.s_score
-- 或者
SELECT
stu.*,
s1.s_score as 01_score,
s2.s_score as 02_score
FROM
Score as s1,
Score as s2,
Student as stu
WHERE
stu.s_id = s1.s_id
AND stu.s_id = s2.s_id
AND s1.c_id = \'01\'
AND s2.c_id = \'02\'
AND s1.s_score > s2.s_score
-- 2、查询"01"课程比"02"课程成绩低的学生的信息及课程分数
SELECT
stu.*,
s1.s_score as 01_score,
s2.s_score as 02_score
FROM
Student as stu
left JOIN Score s1 on stu.s_id = s1.s_id
AND s1.c_id = \'01\'
left JOIN Score s2 on stu.s_id = s2.s_id
AND s2.c_id = \'02\'
or s2.c_id = NULL
where
s1.s_score < s2.s_score
-- 3、查询平均成绩大于等于60分的同学的学生编号和学生姓名和平均成绩
SELECT
s2.s_id,
s2.s_name,
ROUND(AVG(s1.s_score),2) as avg_score
FROM
Score AS s1
left JOIN Student AS s2 on s1.s_id = s2.s_id
GROUP BY
s2.s_id
HAVING AVG(s1.s_score) >=60
-- 4、查询平均成绩小于60分的同学的学生编号和学生姓名和平均成绩
-- (包括有成绩的和无成绩的)
SELECT
s1.s_id,
s1.s_name,
ROUND(AVG(s2.s_score),2) avg_score
FROM
Student AS s1
LEFT JOIN Score s2 on s1.s_id = s2.s_id
GROUP BY
s1.s_id
HAVING AVG(s2.s_score) < 60
union
select
a.s_id,
a.s_name,0 as avg_score
from student a
where a.s_id not in (
select distinct s_id from score
);
-- union用于合并两个或多个结果集,每个结果集必须拥有相同数量的列、列必须拥有相似的数据类型、列的顺序必须相同。
-- 5、查询所有同学的学生编号、学生姓名、选课总数、所有课程的总成绩
SELECT
s1.s_id,
s1.s_name,
count(s2.c_id) as \'课程数\',
SUM(s2.s_score) as \'总分\'
FROM
Student s1
LEFT JOIN Score s2 on s1.s_id = s2.s_id
GROUP BY
s1.s_id
-- 6、查询"李"姓老师的数量
SELECT count(t.t_id) FROM Teacher t WHERE t.t_name LIKE \'李%\'
-- 7、查询学过"张三"老师授课的同学的信息
SELECT s1.*
FROM
Student s1,
Score s2
WHERE
s1.s_id = s2.s_id
AND s2.c_id in (
SELECT c.c_id
FROM
Teacher t,
Course c
where t.t_id = c.t_id
AND t.t_name = \'张三\'
)
-- 8、查询没学过"张三"老师授课的同学的信息
SELECT * FROM Student
WHERE s_id not in (
SELECT s1.s_id
from
Student s1
JOIN Score s2 on s1.s_id = s2.s_id
WHERE s2.c_id in (
select a.c_id
from course a
JOIN teacher b on a.t_id = b.t_id
where t_name =\'张三\'
)
)
-- 9、查询学过编号为"01"并且也学过编号为"02"的课程的同学的信息
SELECT stu.*
from
Student stu,
Score s1,
Score s2
WHERE
s1.c_id = 01
AND s2.c_id = 02
AND s1.s_id = stu.s_id
AND s2.s_id = stu.s_id
-- 10、查询学过编号为"01"但是没有学过编号为"02"的课程的同学的信息
SELECT stu.*
FROM Student stu
WHERE
stu.s_id in (
SELECT s_id
FROM Score
where c_id = 01
)
AND stu.s_id not in (
SELECT s_id
FROM Score
where c_id = 02
)
-- 11、查询没有学全所有课程的同学的信息
SELECT stu.*
FROM Student stu
WHERE stu.s_id not in (SELECT s_id
FROM Score
GROUP BY s_id
HAVING count(*) = (
SELECT count(*) FROM Course
)
)
-- 或者
SELECT stu.*
FROM
Student stu
left join Score sc on stu.s_id = sc.s_id
GROUP BY
stu.s_id
HAVING count(sc.s_id) < (
SELECT count(*) FROM Course
)
-- 12、查询至少有一门课与学号为"01"的同学所学相同的同学的信息
SELECT stu.*
FROM
Student stu,
Score sc
where
stu.s_id = sc.s_id
AND sc.c_id in (
SELECT sc.c_id
FROM Student stu
left join Score sc on stu.s_id = sc.s_id
where stu.s_id = \'01\'
)
GROUP BY stu.s_id HAVING stu.s_id not in (\'01\')
-- 13、查询和"01"号的同学学习的课程完全相同的其他同学的信息
SELECT stu.*
FROM Student stu
WHERE stu.s_id in ( -- 找到与‘01’同学课程数完全一样的同学
SELECT s_id FROM Score
GROUP BY s_id
HAVING count(s_id) = (
-- 找到\'01\'同学学习的课程数
SELECT COUNT(c_id) FROM Score WHERE s_id = \'01\'
)
)
AND stu.s_id not in ( -- 排除学了 \'01\'同学没学过的课程 的同学
SELECT s_id
FROM Score
WHERE c_id in (
SELECT c_id FROM Score
WHERE c_id not in (
-- 找出‘01’同学学习的课程
SELECT c_id FROM Score WHERE s_id = \'01\'
)
)
GROUP BY s_id
)
AND stu.s_id not in (\'01\') -- 排除 \'01\' 同学自己
-- 14、查询没学过"张三"老师讲授的任一门课程的学生姓名
SELECT s_name
FROM Student
where s_id not in ( -- 排除学过‘张三’老师的课的学生
SELECT sc.s_id
FROM Score sc -- 找出学过‘张三’老是的课学生
where sc.c_id in(
select co.c_id
FROM Course co -- 找出‘张三’老师讲授的所有课程
left join Teacher t on t.t_id = co.c_id
where t.t_name = \'张三\'
)
)
-- 15、查询两门及其以上不及格课程的同学的学号,姓名及其平均成绩
SELECT
stu.s_id,
stu.s_name,
sum(sc.s_score)/(SELECT count(c_id) FROM Course)
from
Student stu
left join Score sc on stu.s_id = sc.s_id
where stu.s_id in(
SELECT s_id
FROM Score
where s_score < 60
GROUP BY
s_id
HAVING count(*) >= 2
)
GROUP BY sc.s_id
-- 16、检索"01"课程分数小于60,按分数降序排列的学生信息
SELECT stu.*
FROM
Student stu
left join Score sc on stu.s_id = sc.s_id
and sc.c_id = 01
where stu.s_id in (
SELECT s_id
FROM Score
WHERE s_score < 60
)
ORDER BY
sc.s_score desc
-- 17、按平均成绩从高到低显示所有学生的所有课程的成绩以及平均成绩
SELECT
stu.s_id \'学号\',
stu.s_name \'姓名\',
sum(
case sc.c_id when \'01\' then sc.s_score END
) \'语文\',
sum(
case sc.c_id when \'02\' then sc.s_score END
) \'数学\',
sum(
case sc.c_id when \'03\' then sc.s_score END
) \'英语\',
round(avg(sc.s_score),2) \'平均分\'
FROM
Student stu
left join Score sc on stu.s_id = sc.s_id
GROUP BY
stu.s_id
ORDER BY
6 DESC -- 根据第6列进行排序
-- 18.查询各科成绩最高分、最低分和平均分:以如下形式显示:课程ID,课程name,最高分,最低分,平均分,及格率,中等率,优良率,优秀率
-- 及格为>=60,中等为:70-80,优良为:80-90,优秀为:>=90
SELECT
co.c_id,
co.c_name,
max(sc.s_score) \'最高分\',
min(sc.s_score) \'最低分\',
sum(sc.s_score)/count(stu.s_id) \'平均分\',
round(100*count(
case when sc.s_score >= 60 then sc.s_id END
)/count(stu.s_id),2) \'及格率(%)\',
ROUND(100*count(
case when sc.s_score >= 70 AND sc.s_score < 80 then sc.s_id END
)/count(stu.s_id),2) \'中等率(%)\',
ROUND(100*count(
case when sc.s_score >= 80 AND sc.s_score < 90 then sc.s_id END
)/count(stu.s_id),2) \'优良率(%)\',
ROUND(100*count(
case when sc.s_score >= 90 then sc.s_id END
)/count(stu.s_id),2) \'优秀率(%)\'
FROM
Course co
left join Score sc on sc.c_id = co.c_id
left join Student stu on stu.s_id = sc.s_id
GROUP BY
sc.c_id
-- 20、查询学生的总成绩并进行排名
SELECT
stu.*,
SUM(sc.s_score) as \'总分\',
rank() OVER(ORDER BY SUM(sc.s_score) desc) as \'排名\'
FROM
Student stu
left join Score sc on stu.s_id = sc.s_id
GROUP BY
sc.s_id
ORDER BY SUM(sc.s_score) desc
-- 21、查询不同老师所教不同课程平均分从高到低显示
SELECT
co.c_name,
t.t_name,
ROUND(sum(sc.s_score)/count(co.c_id),2) \'平均分\'
FROM
Course co
left join Score sc on sc.c_id = co.c_id
left join Teacher t on t.t_id = co.t_id
GROUP BY
sc.c_id
ORDER BY 3 desc
-- 22、查询所有课程的成绩第2名到第3名的学生信息及该课程成绩
-- 23、统计各科成绩各分数段人数:课程编号,课程名称,[100-85],[85-70],[70-60],[0-60]及所占百分比
SELECT
co.c_id,
co.c_name,
count(
case when sc.s_score >= 85 then sc.s_id END
) as \'[100-85]\',
count(
case when sc.s_score >= 70 AND sc.s_score < 85 then sc.s_id END
) as \'[85-70]\',
count(
case when sc.s_score >= 60 AND sc.s_score < 70 then sc.s_id END
) as \'[70-60]\',
count(
case when sc.s_score < 60 then sc.s_id END
) as \'[60-0]\'
FROM
Course co
left join Score sc on co.c_id = sc.c_id
left join Student stu on stu.s_id = sc.s_id
GROUP BY
sc.c_id
-- 24、查询学生平均成绩及其名次
SELECT
avg(s_score) as \'平均成绩\',
rank() OVER(ORDER BY AVG(s_score) DESC) as \'名次\'
FROM
Score
GROUP BY
s_id
-- 25、查询各科成绩前三名的记录
SELECT
a.s_id,
a.c_id,
a.s_score
FROM
score a
LEFT JOIN score b ON a.c_id = b.c_id
AND a.s_score < b.s_score
GROUP BY
a.s_id,
a.c_id,
a.s_score
HAVING
COUNT( b.s_id ) < 3
ORDER BY
a.c_id,
a.s_score DESC
-- 26、查询每门课程被选修的学生数
SELECT
co.c_id \'课程ID\',
co.c_name \'课程名\',
count(sc.s_id) \'选修人数\'
FROM
Course co
LEFT JOIN Score sc on sc.c_id = co.c_id
LEFT JOIN Student stu on stu.s_id = sc.s_id
GROUP BY
sc.c_id
-- 27、查询出只有两门课程的全部学生的学号和姓名
SELECT
stu.s_id \'学号\',
stu.s_name \'姓名\'
FROM
Student stu
LEFT JOIN Score sc on sc.s_id = stu.s_id
GROUP BY
sc.s_id
HAVING
count(sc.c_id) = 2
-- 28、查询男生、女生人数
SELECT
s_sex as \'性别\',
count(s_sex) as \'人数\'
FROM
Student
GROUP BY
s_sex
-- 29、查询名字中含有"风"字的学生信息
SELECT * FROM Student WHERE s_name like \'%风%\';
-- 30、查询同名同性学生名单,并统计同名人数
SELECT
a.s_name,
a.s_sex,
count(*)
FROM
Student a
JOIN Student b on a.s_id <> b.s_id
and a.s_name = b.s_name
and a.s_sex = b.s_sex
GROUP BY
a.s_name,
a.s_sex
-- 31、查询1990年出生的学生名单
SELECT * FROM Student where s_birth like \'1990%\'
-- 32、查询每门课程的平均成绩,结果按平均成绩降序排列,平均成绩相同时,按课程编号升序排列
SELECT
c_id,
avg(s_score)
FROM
Score
GROUP BY
c_id
ORDER BY avg(s_score) desc, c_id asc
-- 33、查询平均成绩大于等于85的所有学生的学号、姓名和平均成绩
SELECT
stu.s_id as \'学号\',
stu.s_name as \'姓名\',
avg(s_score) as \'平均成绩\'
FROM
Score sc
LEFT JOIN Student stu on stu.s_id = sc.s_id
GROUP BY
sc.s_id
HAVING avg(s_score) >= 85
-- 34、查询课程名称为"数学",且分数低于60的学生姓名和分数
SELECT
stu.s_id,
stu.s_name,
sc.s_score
FROM
Student stu
LEFT JOIN Score sc ON sc.s_id = stu.s_id
LEFT JOIN Course co ON sc.c_id = co.c_id
WHERE
co.c_name = \'数学\'
AND s_score < 60
-- 35、查询所有学生的课程及分数情况;
SELECT
stu.s_id,
stu.s_name,
stu.s_sex,
sc.c_id,
sc.s_score
FROM
Student stu
LEFT JOIN Score sc on sc.s_id = stu.s_id
-- 36、查询任何一门课程成绩在70分以上的姓名、课程名称和分数
SELECT
stu.s_name,
co.c_name,
sc.s_score
FROM
Student stu
LEFT JOIN Score sc on stu.s_id = sc.s_id
LEFT JOIN Course co on sc.c_id = co.c_id
where
sc.s_score > 70
ORDER BY sc.s_id
-- 37、查询不及格的课程
SELECT
stu.s_id,
stu.s_name,
co.c_name,
sc.s_score
FROM
Student stu
LEFT JOIN Score sc on stu.s_id = sc.s_id
LEFT JOIN Course co on sc.c_id = co.c_id
where
sc.s_score < 60
ORDER BY sc.s_id
-- 38、查询课程编号为01且课程成绩在80分以上的学生的学号和姓名
SELECT
stu.s_id,
stu.s_name,
sc.s_score
FROM
Student stu
LEFT JOIN Score sc on stu.s_id = sc.s_id
LEFT JOIN Course co on sc.c_id = co.c_id
where
co.c_id = \'01\'
and sc.s_score >= 80
ORDER BY sc.s_id
-- 39、求每门课程的学生人数
SELECT
c_id,
count(*)
FROM
Score
GROUP BY c_id
-- 40、查询选修"张三"老师所授课程的学生中,成绩最高的学生信息及其成绩
SELECT
stu.s_name,
sc.s_score
FROM
Student stu
LEFT JOIN Score sc on stu.s_id = sc.s_id
LEFT JOIN Course co on sc.c_id = co.c_id
LEFT JOIN Teacher t on t.t_id = co.t_id
WHERE
t.t_name = \'张三\'
ORDER BY
s_score DESC
LIMIT 0,1
-- 41、查询不同课程成绩相同的学生的学生编号、课程编号、学生成绩
SELECT DISTINCT
a.s_id,
a.c_id,
a.s_score
FROM
Score a
JOIN Score b on a.s_id = b.s_id
and a.s_score = b.s_score
and a.c_id <> b.c_id
ORDER BY a.s_id
-- 42、查询每门课成绩最好的前两名
-- 这写法真牛逼
select
a.s_id,
a.c_id,
a.s_score
from score a
where (
select COUNT(1)
from score b
where
b.c_id=a.c_id
and b.s_score>=a.s_score
)<=2
ORDER BY a.c_id
-- 43、统计每门课程的学生选修人数(超过5人的课程才统计)。要求输出课程号和选修人数,查询结果按人数降序排列,
-- 若人数相同,按课程号升序排列
SELECT
c_id,
count(s_id)
FROM
Score
GROUP BY
c_id
ORDER BY
count(s_id) desc,
c_id asc
-- 44、检索至少选修两门课程的学生学号
SELECT
sc.s_id \'学号\',
count(sc.s_id) \'课程数\'
FROM
Score sc
GROUP BY
sc.s_id
HAVING count(sc.s_id) >= 2
-- 45、查询选修了全部课程的学生信息
SELECT
stu.*
FROM
Student stu
LEFT JOIN Score sc on stu.s_id = sc.s_id
GROUP BY
sc.s_id
HAVING
count(sc.s_id) = (
SELECT count(*) FROM Course
)
-- 46、查询各学生的年龄
SELECT
s_name,
2021 - year(s_birth) \'年龄\'
FROM
Student
-- 47、查询本周过生日的学生
-- 此处可能有问题,week函数取的为当前年的第几周,2017-12-12是第50周而2018-12-12是第49周,可以取月份,day,星期几(%w),
-- 再判断本周是否会持续到下一个月进行判断,太麻烦,不会写
-- 48、查询下周过生日的学生
-- 49、查询本月过生日的学生
SELECT * FROM Student where MONTH(s_birth) = MONTH(NOW())
-- 50、查询下月过生日的学生
-- 注意:当 当前月为12时,用month(now())+1为13而不是1,可用timestampadd()函数或mod取模
select
*
from
student
where
MONTH(NOW())+1 =MONTH(s_birth)
OR MONTH(NOW())-11 =MONTH(s_birth) -- 本月为12月情况
3、SQL表语句
/*
Navicat Premium Data Transfer
Date: 23/06/2021 17:07:38
*/
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for Course
-- ----------------------------
DROP TABLE IF EXISTS `Course`;
CREATE TABLE `Course` (
`c_id` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
`c_name` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT \'\',
`t_id` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
PRIMARY KEY (`c_id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of Course
-- ----------------------------
INSERT INTO `Course` VALUES (\'01\', \'语文\', \'02\');
INSERT INTO `Course` VALUES (\'02\', \'数学\', \'01\');
INSERT INTO `Course` VALUES (\'03\', \'英语\', \'03\');
-- ----------------------------
-- Table structure for Score
-- ----------------------------
DROP TABLE IF EXISTS `Score`;
CREATE TABLE `Score` (
`s_id` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
`c_id` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
`s_score` int(3) DEFAULT NULL,
PRIMARY KEY (`s_id`, `c_id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of Score
-- ----------------------------
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\', 34);
INSERT INTO `Score` VALUES (\'06\', \'03\', 34);
INSERT INTO `Score` VALUES (\'07\', \'01\', 89);
INSERT INTO `Score` VALUES (\'07\', \'03\', 98);
-- ----------------------------
-- Table structure for Student
-- ----------------------------
DROP TABLE IF EXISTS `Student`;
CREATE TABLE `Student` (
`s_id` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
`s_name` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT \'\',
`s_birth` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT \'\',
`s_sex` varchar(10) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT \'\',
PRIMARY KEY (`s_id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of Student
-- ----------------------------
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-07-01\', \'女\');
INSERT INTO `Student` VALUES (\'06\', \'吴兰\', \'1992-03-01\', \'女\');
INSERT INTO `Student` VALUES (\'07\', \'郑竹\', \'1989-06-04\', \'女\');
INSERT INTO `Student` VALUES (\'08\', \'王菊\', \'1990-01-20\', \'女\');
-- ----------------------------
-- Table structure for Teacher
-- ----------------------------
DROP TABLE IF EXISTS `Teacher`;
CREATE TABLE `Teacher` (
`t_id` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
`t_name` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT \'\',
PRIMARY KEY (`t_id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of Teacher
-- ----------------------------
INSERT INTO `Teacher` VALUES (\'01\', \'张三\');
INSERT INTO `Teacher` VALUES (\'02\', \'李四\');
INSERT INTO `Teacher` VALUES (\'03\', \'王五\');
SET FOREIGN_KEY_CHECKS = 1;
参考资料:https://blog.csdn.net/fashion2014/article/details/78826299/