MySQL实战四:查询再续
- 2019 年 10 月 6 日
- 笔记
MySQL学习仓库Up-Up-MySQL,这是一个学习MySQL从入门实战到理论完善,再到精通的一个仓库,后面会把MySQL的学习资料上传上去!欢迎大家star与fork起来!
仓库地址:
https://github.com/Light-City/Up-Up-MySQL
也可以点击阅读原文!
今天上手第四弹,查询再续。
按平均成绩从高到低显示所有学生的所有课程的成绩以及平均成绩
考虑两点:
第一点:平均成绩从高到低排序;
第二点:所有学生;(要想到用join)。
mysql> select * from SC sc left join (select sc.SId, avg(sc.score) AVG from SC sc group by sc.SId order by AVG desc)r on sc.SId=r.SId; +-----+-----+-------+------+----------+ | SId | CId | score | SId | AVG | +-----+-----+-------+------+----------+ | 01 | 01 | 80.0 | 01 | 89.66667 | | 01 | 02 | 90.0 | 01 | 89.66667 | | 01 | 03 | 99.0 | 01 | 89.66667 | | 02 | 01 | 70.0 | 02 | 70.00000 | | 02 | 02 | 60.0 | 02 | 70.00000 | | 02 | 03 | 80.0 | 02 | 70.00000 | | 03 | 01 | 80.0 | 03 | 80.00000 | | 03 | 02 | 80.0 | 03 | 80.00000 | | 03 | 03 | 80.0 | 03 | 80.00000 | | 04 | 01 | 50.0 | 04 | 33.33333 | | 04 | 02 | 30.0 | 04 | 33.33333 | | 04 | 03 | 20.0 | 04 | 33.33333 | | 05 | 01 | 76.0 | 05 | 81.50000 | | 05 | 02 | 87.0 | 05 | 81.50000 | | 06 | 01 | 31.0 | 06 | 32.50000 | | 06 | 03 | 34.0 | 06 | 32.50000 | | 07 | 02 | 89.0 | 07 | 93.50000 | | 07 | 03 | 98.0 | 07 | 93.50000 | +-----+-----+-------+------+----------+ 18 rows in set (0.00 sec)
查询各科成绩最高分、最低分和平均分以如下形式显示: 课程 ID,课程 name,最高分,最低分,平均分,及格率,中等率,优良率,优秀率 及格为>=60,中等为:70-80,优良为:80-90,优秀为:>=90 要求输出课程号和选修人数,查询结果按人数降序排列,若人数相同,按课程号升序排列
SELECT sc.CId '课程 ID', c.Cname '课程 name', MAX(sc.score) AS '最高分' , MIN(sc.score) AS '最低分', AVG(sc.score) AS '平均成绩' , COUNT(sc.CId) AS '选修人数' , SUM(CASE WHEN sc.score >= 60 THEN 1 ELSE 0 END) / COUNT(sc.CId) AS '及格率' , SUM(CASE WHEN sc.score >= 70 AND sc.score < 80 THEN 1 ELSE 0 END) / COUNT(sc.CId) AS '中等率' , SUM(CASE WHEN sc.score >= 80 AND sc.score < 90 THEN 1 ELSE 0 END) / COUNT(sc.CId) AS '优良率' , SUM(CASE WHEN sc.score >= 90 THEN 1 ELSE 0 END) / COUNT(sc.CId) AS '优秀率' FROM SC sc JOIN Course c ON sc.CId = c.CId GROUP BY sc.CId ORDER BY COUNT(sc.CId) DESC, sc.CId ASC;
查询结果:
+-----------+-------------+-----------+-----------+--------------+--------------+-----------+-----------+-----------+-----------+ | 课程 ID | 课程 name | 最高分 | 最低分 | 平均成绩 | 选修人数 | 及格率 | 中等率 | 优良率 | 优秀率 | +-----------+-------------+-----------+-----------+--------------+--------------+-----------+-----------+-----------+-----------+ | 01 | 语文 | 80.0 | 31.0 | 64.50000 | 6 | 0.6667 | 0.3333 | 0.3333 | 0.0000 | | 02 | 数学 | 90.0 | 30.0 | 72.66667 | 6 | 0.8333 | 0.0000 | 0.5000 | 0.1667 | | 03 | 英语 | 99.0 | 20.0 | 68.50000 | 6 | 0.6667 | 0.0000 | 0.3333 | 0.3333 | +-----------+-------------+-----------+-----------+--------------+--------------+-----------+-----------+-----------+-----------+ 3 rows in set (0.00 sec)
统计各科成绩各分数段人数:课程编号,课程名称,[100-85],[85-70],[70-60],[60-0] 及所占百分比
SELECT Course.Cname, Course.CId, SUM(CASE WHEN sc.score <= 100 AND sc.score > 85 THEN 1 ELSE 0 END) AS "[100-85]" , SUM(CASE WHEN sc.score <= 85 AND sc.score > 70 THEN 1 ELSE 0 END) AS "[85-70]", SUM(CASE WHEN sc.score <= 70 AND sc.score > 60 THEN 1 ELSE 0 END) AS "[70-60]" , SUM(CASE WHEN sc.score <= 60 AND sc.score > 0 THEN 1 ELSE 0 END) AS "[60-0]" , SUM(CASE WHEN sc.score <= 100 AND sc.score > 85 THEN 1 ELSE 0 END) / COUNT(1) AS "[100-85]百分比" , SUM(CASE WHEN sc.score <= 85 AND sc.score > 70 THEN 1 ELSE 0 END) / COUNT(1) AS "[85-70]百分比" , SUM(CASE WHEN sc.score <= 70 AND sc.score > 60 THEN 1 ELSE 0 END) / COUNT(1) AS "[70-60]百分比" , SUM(CASE WHEN sc.score <= 60 AND sc.score > 0 THEN 1 ELSE 0 END) / COUNT(1) AS "[60-0]百分比" FROM SC sc LEFT JOIN Course ON sc.CId = Course.CId GROUP BY sc.CId;
查询各科成绩前三名的记录
mysql> select * from SC sc -> where (select count(*) from SC as a -> where sc.CId= a.CId and sc.score<a.score )< 3 -> order by CId asc, sc.score desc; +-----+-----+-------+ | SId | CId | score | +-----+-----+-------+ | 01 | 01 | 80.0 | | 03 | 01 | 80.0 | | 05 | 01 | 76.0 | | 01 | 02 | 90.0 | | 07 | 02 | 89.0 | | 05 | 02 | 87.0 | | 01 | 03 | 99.0 | | 07 | 03 | 98.0 | | 02 | 03 | 80.0 | | 03 | 03 | 80.0 | +-----+-----+-------+ 10 rows in set (0.00 sec)
查询每门课程被选修的学生数
mysql> select CId,count(SId) from SC group by CId; +-----+------------+ | CId | count(SId) | +-----+------------+ | 01 | 6 | | 02 | 6 | | 03 | 6 | +-----+------------+ 3 rows in set (0.00 sec)
查询出只选修两门课程的学生学号和姓名
联合查询:join
连接:
mysql> select s.SId,s.Sname from Student s join SC sc on s.SId=sc.SId group by sc.SId having count(1)=2; +-----+--------+ | SId | Sname | +-----+--------+ | 05 | 周梅 | | 06 | 吴兰 | | 07 | 郑竹 | +-----+--------+ 3 rows in set (0.00 sec)
嵌套查询:in
子句
mysql> select s.SId,s.Sname from Student s where s.SId in (select sc.SId from SC sc group by sc.SId having count(1)=2); +-----+--------+ | SId | Sname | +-----+--------+ | 05 | 周梅 | | 06 | 吴兰 | | 07 | 郑竹 | +-----+--------+ 3 rows in set (0.00 sec)
查询男生、女生人数
mysql> select s.Ssex,count(s.Ssex) as '总人数' from Student s group by s.Ssex; +------+-----------+ | Ssex | 总人数 | +------+-----------+ | 男 | 4 | | 女 | 8 | +------+-----------+ 2 rows in set (0.00 sec)
查询名字中含有“风”字的学生信息
mysql> select * from Student where Sname like '%风%'; +-----+--------+---------------------+------+ | SId | Sname | Sage | Ssex | +-----+--------+---------------------+------+ | 03 | 孙风 | 1990-12-20 00:00:00 | 男 | +-----+--------+---------------------+------+ 1 row in set (0.00 sec)
查询同名学生名单,并统计同名人数
mysql> select s.Sname,count(*) as '同名人数' from Student s group by s.Sname having count(*)>1; +--------+--------------+ | Sname | 同名人数 | +--------+--------------+ | 李四 | 2 | +--------+--------------+ 1 row in set (0.00 sec)
查询1990年出生的学生名单
like
通配符:
mysql> select * from Student where Sage like '1990-%'; +-----+--------+---------------------+------+ | SId | Sname | Sage | Ssex | +-----+--------+---------------------+------+ | 01 | 赵雷 | 1990-01-01 00:00:00 | 男 | | 02 | 钱电 | 1990-12-21 00:00:00 | 男 | | 03 | 孙风 | 1990-12-20 00:00:00 | 男 | | 04 | 李云 | 1990-12-06 00:00:00 | 男 | +-----+--------+---------------------+------+ 4 rows in set, 1 warning (0.00 sec)
year
函数:
mysql> select * from Student where year(Sage)=1990; +-----+--------+---------------------+------+ | SId | Sname | Sage | Ssex | +-----+--------+---------------------+------+ | 01 | 赵雷 | 1990-01-01 00:00:00 | 男 | | 02 | 钱电 | 1990-12-21 00:00:00 | 男 | | 03 | 孙风 | 1990-12-20 00:00:00 | 男 | | 04 | 李云 | 1990-12-06 00:00:00 | 男 | +-----+--------+---------------------+------+ 4 rows in set (0.00 sec)
查询每门课程的平均成绩,结果按平均成绩降序排列,平均成绩相同时,按课程编号升序排列
mysql> select sc.CId,avg(sc.score) as '平均成绩' from SC sc group by sc.CId order by 平均成绩 desc ,sc.CId asc; +-----+--------------+ | CId | 平均成绩 | +-----+--------------+ | 02 | 72.66667 | | 03 | 68.50000 | | 01 | 64.50000 | +-----+--------------+ 3 rows in set (0.00 sec)
查询平均成绩大于等于 85 的所有学生的学号、姓名和平均成绩
mysql> select s.SId,s.Sname,avg(sc.score) as average from Student s left join SC sc on sc.SId=s.SId group by s.SId having average>=85; +-----+--------+----------+ | SId | Sname | average | +-----+--------+----------+ | 01 | 赵雷 | 89.66667 | | 07 | 郑竹 | 93.50000 | +-----+--------+----------+ 2 rows in set (0.00 sec)
查询课程名称为“数学”,且分数低于 60 的学生姓名和分数
mysql> select s.Sname,sc.score from Course c,SC sc,Student s where c.Cname='数学' and c.CId=sc.CId and sc.score<60 and sc.SId=s.SId; +--------+-------+ | Sname | score | +--------+-------+ | 李云 | 30.0 | +--------+-------+ 1 row in set (0.00 sec)
查询所有学生的课程及分数情况(存在学生没成绩,没选课的情况)
mysql> select s.Sname,sc.CId,sc.score from Student s left join SC sc on s.SId=sc.SId; +--------+------+-------+ | Sname | CId | score | +--------+------+-------+ | 赵雷 | 01 | 80.0 | | 赵雷 | 02 | 90.0 | | 赵雷 | 03 | 99.0 | | 钱电 | 01 | 70.0 | | 钱电 | 02 | 60.0 | | 钱电 | 03 | 80.0 | | 孙风 | 01 | 80.0 | | 孙风 | 02 | 80.0 | | 孙风 | 03 | 80.0 | | 李云 | 01 | 50.0 | | 李云 | 02 | 30.0 | | 李云 | 03 | 20.0 | | 周梅 | 01 | 76.0 | | 周梅 | 02 | 87.0 | | 吴兰 | 01 | 31.0 | | 吴兰 | 03 | 34.0 | | 郑竹 | 02 | 89.0 | | 郑竹 | 03 | 98.0 | | 张三 | NULL | NULL | | 李四 | NULL | NULL | | 李四 | NULL | NULL | | 赵六 | NULL | NULL | | 孙七 | NULL | NULL | +--------+------+-------+ 23 rows in set (0.00 sec)
查询任何一门课程成绩在 70 分以上的姓名、课程名称和分数
mysql> select s.Sname, c.Cname,sc.score from Student s,Course c,SC sc -> where sc.score>70 -> and s.SId= sc.SId -> and sc.CId= c.CId; +--------+--------+-------+ | Sname | Cname | score | +--------+--------+-------+ | 赵雷 | 语文 | 80.0 | | 赵雷 | 数学 | 90.0 | | 赵雷 | 英语 | 99.0 | | 钱电 | 英语 | 80.0 | | 孙风 | 语文 | 80.0 | | 孙风 | 数学 | 80.0 | | 孙风 | 英语 | 80.0 | | 周梅 | 语文 | 76.0 | | 周梅 | 数学 | 87.0 | | 郑竹 | 数学 | 89.0 | | 郑竹 | 英语 | 98.0 | +--------+--------+-------+ 11 rows in set (0.00 sec)
查询存在不及格的课程
group by
取唯一:
mysql> select sc.CId from SC sc where sc.score<60 group by sc.CId; +-----+ | CId | +-----+ | 01 | | 02 | | 03 | +-----+ 3 rows in set (0.00 sec)
distinct
取唯一:
mysql> select distinct sc.CId from SC sc where sc.score<60; +-----+ | CId | +-----+ | 01 | | 02 | | 03 | +-----+ 3 rows in set (0.00 sec)
查询课程编号为 01 且课程成绩在 80 分及以上的学生的学号和姓名
mysql> select s.SId,s.Sname from Student s,SC sc where sc.SId=s.SId and sc.score>=80 and sc.CId='01'; +-----+--------+ | SId | Sname | +-----+--------+ | 01 | 赵雷 | | 03 | 孙风 | +-----+--------+ 2 rows in set (0.00 sec)
求每门课程的学生人数
mysql> select sc.CId,count(*) from SC sc group by sc.CId; +-----+----------+ | CId | count(*) | +-----+----------+ | 01 | 6 | | 02 | 6 | | 03 | 6 | +-----+----------+ 3 rows in set (0.00 sec)
查询选修“张三”老师所授课程的学生中,成绩最高的学生信息及其成绩
下面两种方法不管是成绩重复与否,都可以查询出来!
in
子查询:
mysql> select * from Student s,SC sc where s.SId=sc.SId and sc.score =( select max(sc.score) from SC sc,Teacher t,Course c where c.TId=t.TId and c.CId=sc.CId and t.Tname='张三'); +-----+--------+---------------------+------+-----+-----+-------+ | SId | Sname | Sage | Ssex | SId | CId | score | +-----+--------+---------------------+------+-----+-----+-------+ | 01 | 赵雷 | 1990-01-01 00:00:00 | 男 | 01 | 02 | 90.0 | +-----+--------+---------------------+------+-----+-----+-------+ 1 row in set (0.00 sec)
limit
查询
mysql> select s.*,sc.score from Student s,SC sc,Teacher t,Course c where c.TId=t.TId and c.CId=sc.CId and sc.SId=s.SId and t.Tname='张三' order by sc.score desc limit 1; +-----+--------+---------------------+------+-------+ | SId | Sname | Sage | Ssex | score | +-----+--------+---------------------+------+-------+ | 01 | 赵雷 | 1990-01-01 00:00:00 | 男 | 90.0 | +-----+--------+---------------------+------+-------+ 1 row in set (0.01 sec)
查询不同课程成绩相同的学生的学生编号、课程编号、学生成绩
mysql> select distinct sc1.CId,sc1.SId,sc1.score from SC sc1 join SC sc2 on sc1.SId=sc2.SId and sc1.CId!=sc2.CId and sc1.score=sc2.score; +-----+-----+-------+ | CId | SId | score | +-----+-----+-------+ | 02 | 03 | 80.0 | | 03 | 03 | 80.0 | | 01 | 03 | 80.0 | +-----+-----+-------+ 3 rows in set (0.00 sec)
查询每门功成绩最好的前两名
嵌套子查询:
mysql> select * from SC sc -> where (select count(*) from SC as a -> where sc.CId= a.CId and sc.score<a.score )< 2 -> order by CId asc, sc.score desc; +-----+-----+-------+ | SId | CId | score | +-----+-----+-------+ | 01 | 01 | 80.0 | | 03 | 01 | 80.0 | | 01 | 02 | 90.0 | | 07 | 02 | 89.0 | | 01 | 03 | 99.0 | | 07 | 03 | 98.0 | +-----+-----+-------+ 6 rows in set (0.01 sec)
group by having
mysql> select a.SId,a.CId,a.score from SC as a left join SC as b on a.CId=b.CId and a.score<b.score group by a.CId asc,a.SId,a.score desc having count(b.cid)<2 order by a.CId; +-----+-----+-------+ | SId | CId | score | +-----+-----+-------+ | 01 | 01 | 80.0 | | 03 | 01 | 80.0 | | 01 | 02 | 90.0 | | 07 | 02 | 89.0 | | 01 | 03 | 99.0 | | 07 | 03 | 98.0 | +-----+-----+-------+ 6 rows in set, 2 warnings (0.01 sec)
统计每门课程的学生选修人数(超过 5 人的课程才统计)
mysql> select sc.CId,count(sc.SId) as total from SC sc group by sc.CId having total>5; +-----+-------+ | CId | total | +-----+-------+ | 01 | 6 | | 02 | 6 | | 03 | 6 | +-----+-------+ 3 rows in set (0.00 sec)
检索至少选修两门课程的学生学号
mysql> select sc.SId,count(sc.CId) as count from SC sc group by sc.SId having count(sc.CId)>=2; +-----+-------+ | SId | count | +-----+-------+ | 01 | 3 | | 02 | 3 | | 03 | 3 | | 04 | 3 | | 05 | 2 | | 06 | 2 | | 07 | 2 | +-----+-------+ 7 rows in set (0.00 sec)
查询选修了全部课程的学生信息
mysql> select s.* from Student s,SC sc where sc.SId=s.SId group by sc.SId having count(sc.CId)=(select distinct count(*) from Course); +-----+--------+---------------------+------+ | SId | Sname | Sage | Ssex | +-----+--------+---------------------+------+ | 01 | 赵雷 | 1990-01-01 00:00:00 | 男 | | 02 | 钱电 | 1990-12-21 00:00:00 | 男 | | 03 | 孙风 | 1990-12-20 00:00:00 | 男 | | 04 | 李云 | 1990-12-06 00:00:00 | 男 | +-----+--------+---------------------+------+ 4 rows in set (0.00 sec)
查询各学生的年龄,只按年份来算
mysql> select s.Sname,year(curdate())-year(s.Sage) as 年龄 from Student s; +--------+--------+ | Sname | 年龄 | +--------+--------+ | 赵雷 | 29 | | 钱电 | 29 | | 孙风 | 29 | | 李云 | 29 | | 周梅 | 28 | | 吴兰 | 27 | | 郑竹 | 30 | | 张三 | 2 | | 李四 | 2 | | 李四 | 7 | | 赵六 | 6 | | 孙七 | 5 | +--------+--------+ 12 rows in set (0.00 sec)
按照出生日期来算,当前月日 < 出生年月的月日,则年龄减一
mysql> select s.SId,s.Sname,( case -> when MONTH(curdate())<MONTH(s.Sage) then year(curdate())-year(s.Sage)-1 -> when MONTH(s.Sage)=month(curdate()) and DAYOfmonth(s.Sage)<DAYOfmonth(curdate()) -> then year(curdate())-year(s.Sage)-1 -> else year(curdate())-year(s.Sage) -> end) as 年龄 from Student s; +-----+--------+--------+ | SId | Sname | 年龄 | +-----+--------+--------+ | 01 | 赵雷 | 29 | | 02 | 钱电 | 28 | | 03 | 孙风 | 28 | | 04 | 李云 | 28 | | 05 | 周梅 | 27 | | 06 | 吴兰 | 27 | | 07 | 郑竹 | 30 | | 09 | 张三 | 1 | | 10 | 李四 | 1 | | 11 | 李四 | 6 | | 12 | 赵六 | 5 | | 13 | 孙七 | 4 | +-----+--------+--------+ 12 rows in set (0.00 sec)
查询本周过生日的学生
WEEKOFYEAR(date)
返回日期用数字表示的范围是从1到53的日历周。`
mysql> select * from Student s where weekofyear(s.Sage)=weekofyear(curdate()); Empty set (0.00 sec)
查询下周过生日的学生
mysql> select * -> from Student s -> where WEEKOFYEAR(s.Sage)=WEEKOFYEAR(CURDATE())+1; Empty set (0.00 sec)
查询本月过生日的学生
mysql> select * -> from Student s -> where MONTH(s.Sage)=MONTH(CURDATE()); +-----+--------+---------------------+------+ | SId | Sname | Sage | Ssex | +-----+--------+---------------------+------+ | 11 | 李四 | 2012-06-06 00:00:00 | 女 | | 12 | 赵六 | 2013-06-13 00:00:00 | 女 | | 13 | 孙七 | 2014-06-01 00:00:00 | 女 | +-----+--------+---------------------+------+ 3 rows in set (0.00 sec)
查询下月过生日的学生
mysql> select * -> from Student s -> where MONTH(s.Sage)=MONTH(CURDATE())+1; Empty set (0.01 sec)