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
相关推荐
陈敬雷-充电了么-CEO兼CTO39 分钟前
推荐算法系统系列>推荐数据仓库集市的ETL数据处理
大数据·数据库·数据仓库·数据挖掘·数据分析·etl·推荐算法
MeshddY42 分钟前
(超详细)数据库项目初体验:使用C语言连接数据库完成短地址服务(本地运行版)
c语言·数据库·单片机
wuxinyan12342 分钟前
Java面试题033:一文深入了解MySQL(5)
java·数据库·mysql·面试
笑衬人心。1 小时前
Ubuntu 22.04 + MySQL 8 无密码登录问题与 root 密码重置指南
linux·mysql·ubuntu
萧曵 丶1 小时前
Spring @TransactionalEventListener
java·数据库·spring·事务·transactional·异步
坤坤不爱吃鱼1 小时前
【MySQL\Oracle\PostgreSQL】迁移到openGauss数据出现的问题解决方案
mysql·postgresql·oracle
胡斌附体1 小时前
mobaxterm终端sqlplus乱码问题解决
数据库·乱码·sqlplus·字符集设置
moon66sun1 小时前
开源项目XYZ.ESB:数据库到数据库(DB->DB)集成
数据库·esb
欧阳有财2 小时前
[java八股文][Mysql面试篇]日志
java·mysql·面试
TDengine (老段)2 小时前
使用 StatsD 向 TDengine 写入
java·大数据·数据库·时序数据库·iot·tdengine·涛思数据