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
相关推荐
小宇的天下7 分钟前
innovus Flip chip 产品设计方法(3)
数据库·windows·microsoft
龘龍龙14 分钟前
Python基础学习(十一)
python·学习·mysql
GalenZhang88832 分钟前
使用 Python SDK 将数据写入飞书多维表格
数据库·python·飞书·多维表格
云和数据.ChenGuang35 分钟前
GaussDB 期末考试题与面试题
数据库·opengauss·gaussdb·数据库期末试题
不屈的铝合金38 分钟前
SQL 语言概述与数据库核心前置配置了解
数据库·sql·mysql·约束·sql 语句分类·字符集配置·校对规则
萧曵 丶38 分钟前
可重复读(Repeatable Read)隔离级别下幻读产生的原因
数据库·sql·mysql
Antoine-zxt1 小时前
MySQL宕机日志迷局破解指南:从前台启动到精准排错
数据库·mysql·adb
松涛和鸣1 小时前
DAY47 FrameBuffer
c语言·数据库·单片机·sqlite·html
阳宗德1 小时前
基于CentOS Linux release 7.1实现了Oracle Database 11g R2 企业版容器化运行
linux·数据库·docker·oracle·centos
·云扬·1 小时前
MySQL运维效率提升:实用SQL语句合集
运维·sql·mysql