表结构:

`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 JOIN course 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 JOIN course 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 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' );

问题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 FROM score sc WHERE sc.score > 60;

2: 然后获取剩余的学生信息(通过NOT IN)

SELECT st.* FROM student st WHERE st.id NOT IN ( SELECT sc.student_id FROM score 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) FROM score sc WHERE sc.student_id = [特定ID];

3: 获取总成绩(每一个同学的)

SELECT SUM(sc.score) FROM score sc WHERE sc.student_id = [特定ID];

4: 组装SQL

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;

问题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 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 = '叶平老师';

2: 然后在取反、获取剩余的学生信息即可

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 = '叶平老师' );

问题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 JOIN course co ON co.id = sc.course_id WHERE sc.student_id = [特定ID] AND co.name = '001';

2: 统计某一学生是否学过 002 课程的信息

SELECT count(*) FROM score sc LEFT JOIN course 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() 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;

解决方法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 FROM score sc LEFT JOIN course co ON co.id = sc.course_id WHERE co.name = '001';

2: 获取学过 001 课程的学生ID

SELECT sc.student_id FROM score sc LEFT JOIN course co ON co.id = sc.course_id WHERE co.name = '002'

3: 获取即学过 001 又学过 002 课程的学生ID

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;

4:根据学生ID获取学生信息(可以有多种写法)

-- IN 写法:

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;

问题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(*) FROM course );

4:获取学生的所有信息、组合sql 如下:

SELECT st.* FROM student st WHERE (SELECT count(* ) FROM score sc WHERE sc.student_id = st.id) < (SELECT count(*) FROM course);

问题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 FROM student st LEFT JOIN score sc ON sc.student_id = st.id WHERE st.code = '1001';

2: 然后根据获取的课程ID去查所有的学生信息、同时去重即可;

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' );

解决方法 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 FROM student st LEFT JOIN score sc ON sc.student_id = st.id WHERE st.code = '1001';

2: 然后根据获取到课程ID获取学生ID;

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' );

3: 然后获取学生信息

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' ) );

问题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 FROM student st LEFT JOIN score sc ON sc.student_id = st.id WHERE st.code = '1001';

2: 获取对应课程的所有学习同学的ID、并且分组;

SELECT 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' ) GROUP BY sc.student_id;

到此为止发现问题:只学了其中一门的也被查询出来了、应该去掉.

3: 获取学号为 1001 的同学所学课程数量

SELECT COUNT(*) FROM student st LEFT JOIN score sc ON sc.student_id = st.id WHERE st.code = '1001';

4: 所以所有的符合条件的学生的ID集为:

SELECT 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' ) GROUP BY sc.student_id HAVING COUNT() = ( SELECT COUNT() FROM student st LEFT JOIN score 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 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' ) GROUP BY sc.student_id HAVING COUNT() = ( SELECT COUNT() FROM student st LEFT JOIN score 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 JOIN course co ON co.id = sc.course_id LEFT JOIN teacher te ON te.id = co.teache_id WHERE te.name = '叶平老师'

3: 确定要修改的值(获取要修改的数据的平均值)

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

4: 确定修改的条件(获取叶平老师所带课程的ID)

SELECT co.* FROM course co LEFT JOIN teacher 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.* 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 = '叶平老师' );

MYSQL 面试查询系列问题的更多相关文章

  1. 《MySQL面试小抄》查询缓存机制终面

    <MySQL面试小抄>查询缓存机制终面 我是肥哥,一名不专业的面试官! 我是囧囧,一名积极找工作的小菜鸟! 囧囧表示:小白面试最怕的就是面试官问的知识点太笼统,自己无法快速定位到关键问题点 ...

  2. 《MySQL面试小抄》索引考点二面总结

    <MySQL面试小抄>索引考点二面总结 我是肥哥,一名不专业的面试官! 我是囧囧,一名积极找工作的小菜鸟! 囧囧表示:小白面试最怕的就是面试官问的知识点太笼统,自己无法快速定位到关键问题点 ...

  3. MySQL优化篇系列文章(二)——MyISAM表锁与InnoDB锁问题

    我可以和面试官多聊几句吗?只是想... MySQL优化篇系列文章(基于MySQL8.0测试验证),上部分:优化SQL语句.数据库对象,MyISAM表锁和InnoDB锁问题. 面试官:咦,小伙子,又来啦 ...

  4. [MySQL性能优化系列]提高缓存命中率

    1. 背景 通常情况下,能用一条sql语句完成的查询,我们尽量不用多次查询完成.因为,查询次数越多,通信开销越大.但是,分多次查询,有可能提高缓存命中率.到底使用一个复合查询还是多个独立查询,需要根据 ...

  5. [MySQL性能优化系列]巧用索引

    1. 普通青年的索引使用方式 假设我们有一个用户表 tb_user,内容如下: name age sex jack 22 男 rose 21 女 tom 20 男 ... ... ... 执行SQL语 ...

  6. [MySQL性能优化系列]LIMIT语句优化

    1. 背景 假设有如下SQL语句: SELECT * FROM table1 LIMIT offset, rows 这是一条典型的LIMIT语句,常见的使用场景是,某些查询返回的内容特别多,而客户端处 ...

  7. MySQL 5.7系列之sys schema(2)

    0.导读 MySQL 5.7引入了sys schema,有了它,我们排查分析一些问题时将更得心应手.sys schema里主要存储的是视图.存储过程.函数等. 视图:用于结果的汇总展示及配置持久化: ...

  8. MySQL调优系列基础篇

    前言 有一段时间没有写博客了,整天都在忙,上班,录制课程,恰巧最近一段时间比较清闲,打算弄弄MYSQL数据库. 关于MySQL数据库,这里就不做过多的介绍,开源.免费等特性深受各个互联网行业喜爱,尤其 ...

  9. [慢查优化]慎用MySQL子查询,尤其是看到DEPENDENT SUBQUERY标记时

    案例梳理时间:2013-9-25 写在前面的话: 在慢查优化1和2里都反复强调过 explain 的重要性,但有时候肉眼看不出 explain 结果如何指导优化,这时候还需要有一些其他基础知识的佐助, ...

随机推荐

  1. vue组件利用formdata图片预览以及上传《转载》

    转载修改 在项目中直接新建一个单文件页,复制一下代码即可       upload组件: <template> <div class="vue-uploader" ...

  2. 基于TODO的开发方法

    之前买了一本书,叫<架构探险-从零开始写Java Web框架 >(不推荐购买-),一本标题党书籍!但是我很推崇作者写代码的方式,就是基于TODO的方式进行开发! 个人认为以基于TODO的方 ...

  3. Linux Vim查找字符串

    一.用/和?的区别:/后跟查找的字符串.vim会显示文本中第一个出现的字符串.?后跟查找的字符串.vim会显示文本中最后一个出现的字符串.二.注意事项:不管用/还是?查找到第一个字符串后,按回车,vi ...

  4. Java NIO之套接字通道

    1.简介 前面一篇文章讲了文件通道,本文继续来说说另一种类型的通道 -- 套接字通道.在展开说明之前,咱们先来聊聊套接字的由来.套接字即 socket,最早由伯克利大学的研究人员开发,所以经常被称为B ...

  5. Bootstrap3 datetimepicker控件的使用

    Bootstrap3 日期+时间选择控件 1.支持日期选择,格式设定 2.支持时间选择 3.支持时间段选择控制 4.支持中文 官网地址:http://eonasdan.github.io/bootst ...

  6. mysqldump 备份脚本

    #!/bin/bash DUMP=/usr/bin/mysqldump OUT_DIR=/home/mysql LINUX_USER=root DB_NAME=snale DB_USER=root D ...

  7. MQTT TLS 加密传输

    MQTT TLS 加密传输 Mosquitto原生支持了TLS加密,TLS(传输层安全)是SSL(安全套接层)的新名称,生成证书后再配置一下MQTT代理,本文主要介绍Mqtt如何实现双向认证和单向认证 ...

  8. 关于JAVA开发工具IDEA使用

    安装IntelliJ IDEA 一.安装JDK 1 下载最新的jdk,这里下的是jdk-8u66 2 将jdk安装到默认的路径C:\Program Files\Java目录下 二.安装IntelliJ ...

  9. Solr+Tomcat+zookeeper部署实战

    一 .安装solr 环境说明:centos 7.3,solr 6.6,zookeeper3.4,Tomcat8.5,jdk1.8 zookeeper的部署请参考:http://www.cnblogs. ...

  10. 20162308 实验一《Java开发环境的熟悉》实验报告

    a 20162308 实验一<Java开发环境的熟悉>实验报告 实验内容 使用JDK编译.运行简单的Java程序. 使用IDEA 编辑.编译.运行.调试Java程序. 实验要求 没有Lin ...