MySQL经典练习50题(下)(解析版)

所有笔记、生活分享首发于个人博客
想要获得最佳的阅读体验(无广告且清爽),请访问本篇笔记

书接上回(1-25)

经典50题(26-50)

查询每门课被选修的学生数

sql 复制代码
SELECT c.c_name,COUNT(DISTINCT sc.s_id) AS s_num
FROM Score sc 
JOIN Course c ON sc.c_id=c.c_id
GROUP BY c.c_name

成绩表按科目对s_id计数

查询出只有两门课程的全部学生的学号和姓名

sql 复制代码
SELECT s.s_id,s.s_name
FROM Score sc
JOIN Student s ON sc.s_id=s.s_id
GROUP BY s.s_id
HAVING COUNT(DISTINCT sc.c_id)=2

成绩表按学生对c_id计数

查询男女生人数

sql 复制代码
SELECT s_sex,COUNT(DISTINCT s_id) AS '人数'
FROM Student
GROUP BY s_sex

查询名字中含有 风 字的学生信息

sql 复制代码
SELECT * 
FROM Student
WHERE s_name LIKE '%风%'

查询同名同性的学生名单,并统计同名人数

SQL 复制代码
SELECT   s.s_name,  s.s_sex,  COUNT(*) AS same_name_sex_count
FROM   Student AS s
GROUP BY   s.s_name,   s.s_sex
HAVING   COUNT(*) > 1
ORDER BY   s.s_name,   same_name_sex_count DESC;
  1. GROUP BY s.s_name, s.s_sex:根据学生的姓名和性别进行分组,这样具有相同姓名和性别的学生会被分为一组。
  2. HAVING COUNT(*) > 1HAVING 子句用于筛选分组后的结果。这里它用来找出那些出现次数大于1的组,即同名同性的学生。

查询 1990 年出生的学生信息

sql 复制代码
SELECT *
FROM Student
WHERE YEAR(DATE(s_birth))=1990

DATE() 可以将varchar转成日期型

YEAR() 函数返回一个指定日期or时间的年份值,范围为1000到9999,如果日期为零,YEAR()函数返回0

查询每门课程的平均成绩,结果按平均成绩降序排列;平均成绩相同时,按课程编号 c_id 升序排列

SQL 复制代码
SELECT c.c_name,ROUND(AVG(sc.s_score),2) AS '平均分'
FROM Score sc 
JOIN Course c ON sc.c_id=c.c_id
GROUP BY c.c_id
ORDER BY AVG(sc.s_score) DESC,c.c_id ASC

查询平均成绩大于等于 85 的所有学生的学号、姓名和平均成绩

SQL 复制代码
SELECT s.s_id,s.s_name,ROUND(AVG(sc.s_score),2) AS '平均成绩'
FROM Score sc 
JOIN Student s ON sc.s_id=s.s_id
GROUP BY s.s_id
HAVING AVG(sc.s_score)>=85
ORDER BY AVG(sc.s_score) DESC

查询课程名称为数学,且分数低于 60 的学生姓名和分数

sql 复制代码
SELECT s.s_name,sc.s_score
FROM Score sc 
JOIN Student s ON sc.s_id=s.s_id
WHERE c_id=(SELECT c_id FROM Course WHERE c_name='数学')
AND s_score<60
##这题连接三张表也可以

查询所有学生的课程及分数情况

sql 复制代码
SELECT 
  s.s_name,
  SUM(CASE WHEN c.c_name = '语文' THEN sc.s_score ELSE 0 END) AS 语文,
  SUM(CASE WHEN c.c_name = '数学' THEN sc.s_score ELSE 0 END) AS 数学,
  SUM(CASE WHEN c.c_name = '英语' THEN sc.s_score ELSE 0 END) AS 英语,
  SUM(sc.s_score) AS 总分
FROM 
  Student s
LEFT JOIN 
  Score sc ON s.s_id = sc.s_id
LEFT JOIN 
  Course c ON sc.c_id = c.c_id
GROUP BY 
  s.s_name, s.s_id; -- 增加 s.s_id 以确保正确分组

查询任何一门课程成绩在 70 分以上的姓名、课程名称和分数

sql 复制代码
SELECT s.s_name,c.c_name,sc.s_score
FROM Score sc
JOIN Student s ON sc.s_id=s.s_id
JOIN Course c ON sc.s_id=c.c_id
WHERE s_score>70

查询不及格的课程

sql 复制代码
SELECT sc.c_id,c.c_name,sc.s_score
FROM Score sc 
JOIN Course c ON sc.c_id=c.c_id
WHERE sc.s_score<60

查询课程编号为 01 且课程成绩大于等于 80 的学生的学号和姓名

sql 复制代码
SELECT s.s_id,s.s_name
FROM Score sc 
LEFT JOIN Student s ON sc.s_id=s.s_id
WHERE c_id='01'
AND s_score>=80

每门课程的学生人数

sql 复制代码
SELECT c.c_name,count(DISTINCT sc.s_id) AS '人数'
FROM Score sc
JOIN Course c ON sc.c_id=c.c_id
GROUP BY c.c_name

查询选修"张三"老师所授课程的学生中,成绩最高的学生信息及其成绩

sql 复制代码
SELECT   s.*,  MAX(sc.s_score) AS 最高成绩
FROM   Student AS s
JOIN   Score AS sc ON s.s_id = sc.s_id
JOIN   Course AS c ON sc.c_id = c.c_id
JOIN   Teacher AS t ON c.t_id = t.t_id
WHERE   t.t_name = '张三'
GROUP BY   s.s_id,   s.s_name -- 避免同名
ORDER BY   最高成绩 DESC
LIMIT 1;

查询不同课程成绩相同的学生的学生编号、课程编号、学生成绩

SQL 复制代码
SELECT sc1.s_id,sc1.c_id,sc1.s_score
FROM Score AS sc1
JOIN Score AS sc2 ON sc1.s_score = sc2.s_score  AND sc1.c_id <> sc2.c_id
GROUP BY sc1.s_id, sc1.c_id, sc1.s_score
HAVING 		COUNT(DISTINCT sc2.c_id) > 1;
  1. 将成绩表自身进行连接(自连接),连接条件是两个不同的成绩记录具有相同的分数,但课程编号不同。
  2. HAVING 子句用于筛选分组后的结果,这里它用来找出那些在多个不同课程中具有相同成绩的学生记录。

查询每门功课成绩最好的前两名

sql 复制代码
SELECT r.*	
FROM(
SELECT c_name,s_name,s_score,
ROW_NUMBER()OVER(PARTITION BY c_name ORDER BY s_score DESC) as rank_num
FROM Score sc 
JOIN Course c ON sc.c_id=c.c_id
JOIN student s ON sc.s_id=s.s_id)  r
WHERE r.rank_num<=2

窗口函数 ROW_NUMBER() 为每个课程 (PARTITION BY c_name) 的成绩分配一个唯一的序号,按分数降序排列 (ORDER BY s_score DESC)。

通过相应的 ID 关联这三个表,以获取完整的课程和学生信息以及他们的分数。

最后通过where筛选出每门课程成绩排名前两名的学生。

统计每门课程的学生选修人数(超过 5 人的课程才统计)。要求输出课程号和选修人数,查询结果按人数降序排列, 若人数相同,按课程号升序排列

SQL 复制代码
SELECT c_id,COUNT(DISTINCT s_id) AS NUMS
FROM Score
GROUP BY c_id
ORDER BY NUMS DESC,c_id ASC

检索至少选修两门课程的学生学号

SQL 复制代码
SELECT s_id
FROM Score
GROUP BY s_id
HAVING COUNT(DISTINCT c_id)>=2S

查询选修了全部课程的学生信息

sql 复制代码
SELECT s.*
FROM student s
JOIN score sc ON s.s_id = sc.s_id
GROUP BY s.s_id
HAVING COUNT(DISTINCT c_id)=(SELECT COUNT(*)FROM course)

查询各学生的年龄:按照出生日期来算,当前月日 < 出生年月的月日则,年龄减 1

sql 复制代码
SELECT s.*,
CASE 
	WHEN MONTH(NOW())<MONTH(DATE(s_birth)) THEN
		YEAR(NOW())-YEAR(DATE(s_birth))-1
	WHEN MONTH(NOW())=MONTH(DATE(s_birth)) AND DAY(NOW())<DAY(DATE(s_birth)) THEN
		YEAR(NOW())-YEAR(DATE(s_birth))-1
	ELSE
		YEAR(NOW())-YEAR(DATE(s_birth))
END AS age
FROM Student s

查询本周过生日的学生

sql 复制代码
SELECT s.*
FROM student s
WHERE WEEK(DATE(s.s_birth))=WEEK(NOW())

查询下周过生日的学生

sql 复制代码
SELECT s.*
FROM student s
WHERE WEEK(DATE(s.s_birth))=WEEK(NOW())+1

查询本月过生的同学

sql 复制代码
SELECT s.*
FROM student s
WHERE MONTH(DATE(s.s_birth))=MONTH(NOW())

查询下月过生日的学生

sql 复制代码
SELECT s.*
FROM student s
WHERE MONTH(DATE(s.s_birth))=MONTH(NOW())+1
相关推荐
CoderIsArt34 分钟前
Redis的三种模式:主从模式,哨兵与集群模式
数据库·redis·缓存
师太,答应老衲吧3 小时前
SQL实战训练之,力扣:2020. 无流量的帐户数(递归)
数据库·sql·leetcode
Yaml43 小时前
Spring Boot 与 Vue 共筑二手书籍交易卓越平台
java·spring boot·后端·mysql·spring·vue·二手书籍
Channing Lewis4 小时前
salesforce case可以新建一个roll up 字段,统计出这个case下的email数量吗
数据库·salesforce
追风林4 小时前
mac 本地docker-mysql主从复制部署
mysql·macos·docker
毕业设计制作和分享5 小时前
ssm《数据库系统原理》课程平台的设计与实现+vue
前端·数据库·vue.js·oracle·mybatis
ketil275 小时前
Redis - String 字符串
数据库·redis·缓存
Hsu_kk6 小时前
MySQL 批量删除海量数据的几种方法
数据库·mysql
编程学无止境6 小时前
第02章 MySQL环境搭建
数据库·mysql
knight-n6 小时前
MYSQL库的操作
数据库·mysql