MYSQL查询系列 常考问题
表结构:
`student`('id'、'name'、'code'、'age'、'sex')学生表
`teacher`('id'、'name')教师表
`course`('id'、'name'、'teacher_id')课程表
`score`('student_id'、'course_id'、'score')成绩表
问题:
1: 查询001课程比002课程成绩高的所有学生的信息
2: 查询所有课程成绩小于60分的同学的信息
3: 查询平均成绩大于60分的同学平均成绩和学生的信息
4: 查询所有同学的信息、选课数、总成绩
5: 查询没学过 “叶平老师” 课的同学的信息
6: 查询学过“001”并且也学过编号“002”课程的同学的信息
7: 查询没有学全所有课的同学的信息
8: 查询至少有一门课与学号为“1001”的同学所学相同同学的信息
9: 查询至少学过学号为1001的同学所有课程的 其他同学的信息
10: 把“score”表中“叶平老师”教的课的成绩都更改为此课程的平均成绩
解决:
创建表
CREATE TABLE `student` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(30) DEFAULT NULL,
`code` varchar(15) DEFAULT NULL,
`age` int(11) DEFAULT NULL,
`sex` int(11) DEFAULT '1' COMMENT '1 男 2 女',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4;
CREATE TABLE `teacher` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(30) DEFAULT '' COMMENT '老师名',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4;
CREATE TABLE `course` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(30) DEFAULT NULL COMMENT '课程名',
`teache_id` int(11) DEFAULT NULL COMMENT '教师ID',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4;
CREATE TABLE `score` (
`student_id` int(11) DEFAULT NULL COMMENT '学生ID',
`course_id` int(11) DEFAULT NULL COMMENT '课程ID',
`score` int(11) DEFAULT NULL COMMENT '成绩'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
问题1: 查询001课程比002课程成绩高的所有学生的信息;
SELECT st.* FROM student st WHERE ( SELECT sc.`score` FROM score sc LEFT JOIN `course` co ON co.`id`=sc.`course_id` WHERE st.`id` = sc.`student_id` AND co.`name` = '001' ) > ( SELECT sc.`score` FROM score sc LEFT JOIN `course` co ON co.`id`=sc.`course_id` WHERE st.`id` = sc.`student_id` AND co.`name` = '002' );
分解:
1: 按题意理解、写的如下SQL
SELECT st.* FROM student st WHERE ( ) > ( );
2: 获取指定ID的学生的001课程的成绩
SELECT sc.
score
FROM score sc LEFT JOINcourse
co ON co.id
=sc.course_id
WHERE [指定ID] = sc.student_id
AND co.name
= '001';3: 获取指定ID的学生的002课程的成绩
SELECT sc.
score
FROM score sc LEFT JOINcourse
co ON co.id
=sc.course_id
WHERE [指定ID] = sc.student_id
AND co.name
= '002';4: 组装SQL
SELECT st.* FROM student st WHERE ( SELECT sc.
score
FROM score sc LEFT JOINcourse
co ON co.id
=sc.course_id
WHERE st.id
= sc.student_id
AND co.name
= '001' ) > ( SELECT sc.score
FROM score sc LEFT JOINcourse
co ON co.id
=sc.course_id
WHERE st.id
= sc.student_id
AND co.name
= '002' );
问题2: 查询所有课程成绩小于60分的同学的信息;
SELECT st.* FROM `student` st WHERE st.id NOT IN ( SELECT sc.`student_id` FROM `score` sc WHERE sc.`score` > 60 );
分解:
1: 先是获取成绩大于60的同学 (题意是所有成绩都小于60的才符合、那么排除只要有一门成绩大于60的即可)
SELECT sc.
student_id
FROMscore
sc WHERE sc.score
> 60;2: 然后获取剩余的学生信息(通过NOT IN)
SELECT st.* FROM
student
st WHERE st.id
NOT IN ( SELECT sc.student_id
FROMscore
sc WHERE sc.score
> 60 );
问题3: 查询平均成绩大于60分的同学的学号和平均成绩和学生的信息;
SELECT st.*,AVG( sc.`score`) as AvgScore FROM `score` sc LEFT JOIN student st ON st.`id` = sc.`student_id` GROUP BY sc.`student_id` HAVING AVG( sc.`score` ) > 60;
注意:
HAVING 应用与对 where 和 group by 查询出来的分组进行过滤、查询出满足条件的分组结果。
1> having 只能应用与 group by(分组统计语句中)
2> where 是用于在初始表中筛选查询,having用于在where和group by 结果分组中查询
3> having 子句中的每一个元素也必须出现在select列表中
4> having语句可以使用聚合函数,而where不使用
问题4: 查询所有同学的信息、选课数、总成绩;
SELECT st.*,(SELECT COUNT( sc.`course_id`) FROM `score` sc WHERE sc.`student_id` = st.`id` ) courseNum, (SELECT SUM(sc.`score`) FROM `score` sc WHERE sc.`student_id` = st.`id`) scoreNum FROM student st;
分解:
1: 获取所有同学的信息
SELECT st.* FROM student st;
2: 获取选课数( 每一个同学都是一个特定的ID)
SELECT COUNT( sc.
course_id
) FROMscore
sc WHERE sc.student_id
= [特定ID];3: 获取总成绩(每一个同学的)
SELECT SUM(sc.
score
) FROMscore
sc WHERE sc.student_id
= [特定ID];4: 组装SQL
SELECT st.*,(SELECT COUNT( sc.
course_id
) FROMscore
sc WHERE sc.student_id
= st.id
) courseNum, (SELECT SUM(sc.score
) FROMscore
sc WHERE sc.student_id
= st.id
) scoreNum FROM student st;
问题5: 查询没学过 “叶平老师” 课的同学信息
SELECT st.* FROM `student` st WHERE st.`id` NOT IN ( SELECT sc.`student_id` FROM `score` sc LEFT JOIN `course` co ON co.`id` = sc.`course_id` LEFT JOIN `teacher` te ON te.`id` = co.`teache_id` WHERE te.`name` = '叶平老师' );
分解:
1: 根据题意、取反、先获取学过“叶平老师”课的同学
SELECT sc.
student_id
FROMscore
sc LEFT JOINcourse
co ON co.id
= sc.course_id
LEFT JOINteacher
te ON te.id
= co.teache_id
WHERE te.name
= '叶平老师';2: 然后在取反、获取剩余的学生信息即可
SELECT st.* FROM
student
st WHERE st.id
NOT IN ( SELECT sc.student_id
FROMscore
sc LEFT JOINcourse
co ON co.id
= sc.course_id
LEFT JOINteacher
te ON te.id
= co.teache_id
WHERE te.name
= '叶平老师' );
问题6: 查询学过“001”也学过编号“002”课程的同学信息
解决方法1:
SELECT st.* FROM `student` st WHERE (SELECT count(*) FROM `score` sc LEFT JOIN `course` co ON co.`id` = sc.`course_id` WHERE sc.`student_id` = st.`id` AND co.`name` = '001') > 0 AND (SELECT count(*) FROM `score` sc LEFT JOIN `course` co ON co.`id` = sc.`course_id` WHERE sc.`student_id` = st.`id` AND co.`name` = '002') > 0;
分解:
1: 统计某一学生是否学过 001 课程的信息
SELECT count(*) FROM
score
sc LEFT JOINcourse
co ON co.id
= sc.course_id
WHERE sc.student_id
= [特定ID] AND co.name
= '001';2: 统计某一学生是否学过 002 课程的信息
SELECT count(*) FROM
score
sc LEFT JOINcourse
co ON co.id
= sc.course_id
WHERE sc.student_id
= [特定ID] AND co.name
= '002';3: 直接获取 条件1 和 条件2 同时成立的数据
SELECT st.* FROM
student
st WHERE (SELECT count() FROMscore
sc LEFT JOINcourse
co ON co.id
= sc.course_id
WHERE sc.student_id
= st.id
AND co.name
= '001') > 0 AND (SELECT count() FROMscore
sc LEFT JOINcourse
co ON co.id
= sc.course_id
WHERE sc.student_id
= st.id
AND co.name
= '002') > 0;
解决方法2:
SELECT * FROM `student` st WHERE st.`id` IN ( SELECT st1.student_id FROM ( SELECT sc.`student_id` FROM `score` sc LEFT JOIN `course` co ON co.`id` = sc.`course_id` WHERE co.`name` = '001' ) st1,( SELECT sc.`student_id` FROM `score` sc LEFT JOIN `course` co ON co.`id` = sc.`course_id` WHERE co.`name` = '002' )st2 WHERE st1.`student_id` = st2.`student_id` );
或者
SELECT st.* FROM `student` st,(SELECT st1.student_id FROM ( SELECT sc.`student_id` FROM `score` sc LEFT JOIN `course` co ON co.`id` = sc.`course_id` WHERE co.`name` = '001' ) st1,( SELECT sc.`student_id` FROM `score` sc LEFT JOIN `course` co ON co.`id` = sc.`course_id` WHERE co.`name` = '002' )st2 WHERE st1.`student_id` = st2.`student_id`) st3 WHERE st3.`student_id`= st.`id`;
分解:
1: 获取学过 001 课程的学生ID
SELECT sc.
student_id
FROMscore
sc LEFT JOINcourse
co ON co.id
= sc.course_id
WHERE co.name
= '001';2: 获取学过 001 课程的学生ID
SELECT sc.
student_id
FROMscore
sc LEFT JOINcourse
co ON co.id
= sc.course_id
WHERE co.name
= '002'3: 获取即学过 001 又学过 002 课程的学生ID
SELECT st1.student_id FROM ( SELECT sc.
student_id
FROMscore
sc LEFT JOINcourse
co ON co.id
= sc.course_id
WHERE co.name
= '001' ) st1, ( SELECT sc.student_id
FROMscore
sc LEFT JOINcourse
co ON co.id
= sc.course_id
WHERE co.name
= '002' ) st2 WHERE st1.student_id
= st2.student_id
;4:根据学生ID获取学生信息(可以有多种写法)
-- IN 写法:
SELECT * FROMstudent
st WHERE st.id
IN ( SELECT st1.student_id FROM ( SELECT sc.student_id
FROMscore
sc LEFT JOINcourse
co ON co.id
= sc.course_id
WHERE co.name
= '001' ) st1,( SELECT sc.student_id
FROMscore
sc LEFT JOINcourse
co ON co.id
= sc.course_id
WHERE co.name
= '002' )st2 WHERE st1.student_id
= st2.student_id
);
-- 把结果当作一个表、起别名再去查询:
SELECT st.* FROMstudent
st,(SELECT st1.student_id FROM ( SELECT sc.student_id
FROMscore
sc LEFT JOINcourse
co ON co.id
= sc.course_id
WHERE co.name
= '001' ) st1,( SELECT sc.student_id
FROMscore
sc LEFT JOINcourse
co ON co.id
= sc.course_id
WHERE co.name
= '002' )st2 WHERE st1.student_id
= st2.student_id
) st3 WHERE st3.student_id
= st.id
;
问题7: 查询没有学全所有课的同学的信息
SELECT st.* FROM `student` st WHERE (SELECT count(*) FROM `score` sc WHERE sc.`student_id` = st.`id`) < (SELECT count(*) FROM `course`);
分解:
1: 获取课的总数;
SELECT count(*) FROM
course
;2: 获取每个人的学习的课的总数;
SELECT count(*) FROM
score
sc WHERE sc.student_id
= [特定ID];3: 然后查询的是 没有学全所有课的学生、也就是学习的课数小于总课数
(SELECT count(* ) FROM
score
sc WHERE sc.student_id
= [特定ID]) < (SELECT count(*) FROMcourse
);4:获取学生的所有信息、组合sql 如下:
SELECT st.* FROM
student
st WHERE (SELECT count(* ) FROMscore
sc WHERE sc.student_id
= st.id
) < (SELECT count(*) FROMcourse
);
问题8: 查询至少有一门课与学号为1001的同学所学相同同学的信息
解决方法 1:
SELECT DISTINCT st.* FROM `student` st INNER JOIN `score` sc ON sc.`student_id` = st.`id` WHERE sc.`course_id` IN ( SELECT sc.`course_id` FROM `student` st LEFT JOIN `score` sc ON sc.`student_id` = st.`id` WHERE st.`code` = '1001' );
分解:
先获取到学号为1001同学的所有学习课程、然后根据获取的课程ID去查所有的学生信息、然后 DISTINCT 去重即可。
1: 先获取到学号为1001同学的所有学习课程;
SELECT sc.
course_id
FROMstudent
st LEFT JOINscore
sc ON sc.student_id
= st.id
WHERE st.code
= '1001';2: 然后根据获取的课程ID去查所有的学生信息、同时去重即可;
SELECT DISTINCT st.* FROM
student
st INNER JOINscore
sc ON sc.student_id
= st.id
WHERE sc.course_id
IN ( SELECT sc.course_id
FROMstudent
st LEFT JOINscore
sc ON sc.student_id
= st.id
WHERE st.code
= '1001' );
解决方法 2:
SELECT st.* FROM `student` st WHERE st.`id` IN ( SELECT DISTINCT sc.`student_id` FROM `score` sc WHERE sc.`course_id` IN ( SELECT sc.`course_id` FROM `student` st LEFT JOIN `score` sc ON sc.`student_id` = st.`id` WHERE st.`code` = '1001' ) );
分解:
先获取学号为1001学生的课程、然后根据获取到课程ID获取学生ID、然后去重、然后获取学生信息。(嵌套子查询)
1: 先获取到学号为1001同学的所有学习课程;
SELECT sc.
course_id
FROMstudent
st LEFT JOINscore
sc ON sc.student_id
= st.id
WHERE st.code
= '1001';2: 然后根据获取到课程ID获取学生ID;
SELECT DISTINCT sc.
student_id
FROMscore
sc WHERE sc.course_id
IN ( SELECT sc.course_id
FROMstudent
st LEFT JOINscore
sc ON sc.student_id
= st.id
WHERE st.code
= '1001' );3: 然后获取学生信息
SELECT st.* FROM
student
st WHERE st.id
IN ( SELECT DISTINCT sc.student_id
FROMscore
sc WHERE sc.course_id
IN ( SELECT sc.course_id
FROMstudent
st LEFT JOINscore
sc ON sc.student_id
= st.id
WHERE st.code
= '1001' ) );
问题9: 查询至少学过学号为1001的同学所有课程的 其他同学的信息
SELECT st.* FROM `student` st WHERE st.`id` IN ( SELECT sc1.`student_id` FROM ( SELECT sc.* FROM `score` sc WHERE sc.`course_id` IN ( SELECT sc.`course_id` FROM `student` st LEFT JOIN `score` sc ON sc.`student_id` = st.`id` WHERE st.`code` = '1001' ) ) sc1 GROUP BY sc1.`student_id` HAVING COUNT(*) = ( SELECT COUNT(*) FROM `student` st LEFT JOIN `score` sc ON sc.`student_id` = st.`id` WHERE st.`code` = '1001' ) );
分解:
1: 获取学号为 1001 的同学的所有课程ID;
SELECT sc.
course_id
FROMstudent
st LEFT JOINscore
sc ON sc.student_id
= st.id
WHERE st.code
= '1001';2: 获取对应课程的所有学习同学的ID、并且分组;
SELECT sc.
student_id
FROMscore
sc WHERE sc.course_id
IN ( SELECT sc.course_id
FROMstudent
st LEFT JOINscore
sc ON sc.student_id
= st.id
WHERE st.code
= '1001' ) GROUP BY sc.student_id
;到此为止发现问题:只学了其中一门的也被查询出来了、应该去掉.
3: 获取学号为 1001 的同学所学课程数量
SELECT COUNT(*) FROM
student
st LEFT JOINscore
sc ON sc.student_id
= st.id
WHERE st.code
= '1001';4: 所以所有的符合条件的学生的ID集为:
SELECT sc.
student_id
FROMscore
sc WHERE sc.course_id
IN ( SELECT sc.course_id
FROMstudent
st LEFT JOINscore
sc ON sc.student_id
= st.id
WHERE st.code
= '1001' ) GROUP BY sc.student_id
HAVING COUNT() = ( SELECT COUNT() FROMstudent
st LEFT JOINscore
sc ON sc.student_id
= st.id
WHERE st.code
= '1001' );5: 组装SQL、查询学生信息。
SELECT st.* FROM
student
st WHERE st.id
IN ( SELECT sc.student_id
FROMscore
sc WHERE sc.course_id
IN ( SELECT sc.course_id
FROMstudent
st LEFT JOINscore
sc ON sc.student_id
= st.id
WHERE st.code
= '1001' ) GROUP BY sc.student_id
HAVING COUNT(*) >= ( SELECT COUNT(*) FROMstudent
st LEFT JOINscore
sc ON sc.student_id
= st.id
WHERE st.code
= '1001' ) );
问题10: 把“score”表中“叶平老师”教的课的成绩都更改为此课程的平均成绩
UPDATE `score` sc SET sc.`score` = ( SELECT AVG(sc1.`score`) avgScore FROM (SELECT sc.* FROM `score` sc LEFT JOIN `course` co ON co.`id` = sc.`course_id` LEFT JOIN `teacher` te ON te.`id` = co.`teache_id` WHERE te.`name` = '叶平老师' ) sc1 ) WHERE sc.`course_id` = ( SELECT co.`id` FROM `course` co LEFT JOIN `teacher` te ON te.`id` = co.`teache_id` WHERE te.`name` = '叶平老师' );
分解:
1: 理解为修改特定ID的数据
UPDATE
score
sc SET sc.score
= () WHERE sc.course_id
= ();2: 要修改的数据( 获取“score”表中“叶平老师”教的课的成绩)
SELECT sc.* FROM
score
sc LEFT JOINcourse
co ON co.id
= sc.course_id
LEFT JOINteacher
te ON te.id
= co.teache_id
WHERE te.name
= '叶平老师'3: 确定要修改的值(获取要修改的数据的平均值)
SELECT AVG(sc1.
score
) avgScore FROM (SELECT sc.* FROMscore
sc LEFT JOINcourse
co ON co.id
= sc.course_id
LEFT JOINteacher
te ON te.id
= co.teache_id
WHERE te.name
= '叶平老师' ) sc14: 确定修改的条件(获取叶平老师所带课程的ID)
SELECT co.* FROM
course
co LEFT JOINteacher
te ON te.id
= co.teache_id
WHERE te.name
= '叶平老师'5: 组装SQL即可
UPDATE
score
sc SET sc.score
= ( SELECT AVG(sc1.score
) avgScore FROM (SELECT sc.* FROMscore
sc LEFT JOINcourse
co ON co.id
= sc.course_id
LEFT JOINteacher
te ON te.id
= co.teache_id
WHERE te.name
= '叶平老师' ) sc1 ) WHERE sc.course_id
in ( SELECT co.id
FROMcourse
co LEFT JOINteacher
te ON te.id
= co.teache_id
WHERE te.name
= '叶平老师' );
MYSQL查询系列 常考问题的更多相关文章
- 为什么你学不会递归?告别递归,谈谈我的一些经验 关于集合中一些常考的知识点总结 .net辗转java系列(一)视野 彻底理解cookie,session,token
为什么你学不会递归?告别递归,谈谈我的一些经验 可能很多人在大一的时候,就已经接触了递归了,不过,我敢保证很多人初学者刚开始接触递归的时候,是一脸懵逼的,我当初也是,给我的感觉就是,递归太神奇了! ...
- 近5年常考Java面试题及答案整理(三)
上一篇:近5年常考Java面试题及答案整理(二) 68.Java中如何实现序列化,有什么意义? 答:序列化就是一种用来处理对象流的机制,所谓对象流也就是将对象的内容进行流化.可以对流化后的对象进行读写 ...
- mysql:10道mysql查询语句面试题
表结构 学生表student(id,name) 课程表course(id,name) 学生课程表student_course(sid,cid,score) 创建表的sql代码 ```sql creat ...
- PHP面试常考内容之Memcache和Redis(1)
你好,是我琉忆.继上周(2019.2-11至2-15)发布的"PHP面试常考内容之面向对象"专题后,发布的第二个专题,感谢你的阅读.本周(2019.2-18至2-22)的文章内容点 ...
- Mysql优化系列(2)--通用化操作梳理
前面有两篇文章详细介绍了mysql优化举措:Mysql优化系列(0)--总结性梳理Mysql优化系列(1)--Innodb引擎下mysql自身配置优化 下面分类罗列下Mysql性能优化的一些技巧,熟练 ...
- MySQL学习系列2--MySQL执行计划分析EXPLAIN
原文:MySQL学习系列2--MySQL执行计划分析EXPLAIN 1.Explain语法 EXPLAIN SELECT …… 变体: EXPLAIN EXTENDED SELECT …… 将执行 ...
- C/C++常考面试题(一)
这算是一个系列吧,记录一下在准备秋招期间,所准备的C++面试题,望秋招顺利.所有的面试题均来源于各大论坛,网络. C/C++常考面试题(一) 常用的C++数据结构有哪些? vector,序列式容器,相 ...
- MYSQL查询语句大全集锦
MYSQL查询语句大全集锦 1:使用SHOW语句找出在服务器上当前存在什么数据库: mysql> SHOW DATABASES; 2:2.创建一个数据库MYSQLDATA mysql> C ...
- (转)MySQL优化系列
原文:http://blog.csdn.net/jack__frost/article/details/71194208 数据库,后端开发者必学,而且现在以MySQL居多.这个系列将系统化MySQL一 ...
随机推荐
- luogu P3767 膜法
传送门 这题如果没有删除操作,可以直接使用可持久化并查集 注意到这种可持久化的依赖关系(是这样说的把)是一棵树,然后对于一个点,自己的操作会影响自己的那棵子树,并且如果是删除操作,就会使得一个子树没有 ...
- JDK开发环境搭建及环境变量配置
Java配置----JDK开发环境搭建及环境变量配置 1. 下载安装安装JDK开发环境 http://www.oracle.com/technetwork/java/javase/downloads/ ...
- Loadrunner 如何在其他浏览器进行录制(一)
背景: 由于lr只支持低版本的IE浏览器,当我们想使用高版本或其他浏览器进行录制时,这时,我们需要用到浏览器的代理功能. 传统的访问模式如下: 使用代理后的访问方式: 下面来总结一下具体的步骤: 1. ...
- cmder使用简介
简介 cmder是一个增强型命令行工具,不仅可以使用windows下的所有命令,更爽的是可以使用linux的命令,shell命令. 下载 官网地址:http://cmder.net/ 下载的时候,会有 ...
- Python笔记 【无序】 【四】
魔法方法1.__xx__ 总是被双下划线包围2.面向对象python的一切 3.能够在适当的时候自动被调用 构造和析构 __init__(self,……) -----相当于构造方法,类在实例 ...
- 【转】python之random模块分析(一)
[转]python之random模块分析(一) random是python产生伪随机数的模块,随机种子默认为系统时钟.下面分析模块中的方法: 1.random.randint(start,stop): ...
- Go语言中的map
map是一个集合,可以使用类似处理数组和切片的方式迭代map中的元素.但map是无序的集合.无序的原因是map的实现使用了散列表. map的创建并初始化主要是两种方式: 1.内置的make函数 2.使 ...
- Linux的notifier机制在TP中的应用【转】
转自:https://blog.csdn.net/armfpga123/article/details/51771666 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog ...
- Valgrind使用【转】
转自:https://www.cnblogs.com/napoleon_liu/articles/2001802.html 调不尽的内存泄漏,用不完的Valgrind Valgrind 安装 1. 到 ...
- Python运维开发基础08-文件基础【转】
一,文件的其他打开模式 "+"表示可以同时读写某个文件: r+,可读写文件(可读:可写:可追加) w+,写读(不常用) a+,同a(不常用 "U"表示在读取时, ...