2023.12.13 关于 MySQL 复杂查询

目录

聚合查询

聚合函数

group by 子句

执行流程图

联合查询 

笛卡尔积

内连接 外连接

左外连接

右外连接

自连接

子查询

单行子查询

多行子查询

EXISTS 关键字

合并查询

union on 和 union 的区别


聚合查询

聚合函数

函数说明
COUNT([DISTINCT] expr)返回查询到的数据的数量
SUM([DISTINCT] expr)返回查询到的数据的总和
AVG([DISTINCT] expr)返回查询到的数据的平均值
MAX([DISTINCT] expr)返回查询到的数据的最大值
MIN([DISTINCT] expr)返回查询到的数据的最小值

注意:

  • 求和、平均值、最大、最小 这几个函数都需要针对数字类型的列

实例理解

  • 此处我们创建一个 exam_result 表,并插入几条数据

  • 使用 count 查询返回结果的行数
select count(*) from exam_result;

执行结果:

  • 使用 sum 查询 chines 字段数据的和(针对某一列计算)
select sum(chinese) from exam_result;

 执行结果:

  • 使用 avg 查询 chines + math + eglish  这三个字段数据的平均值(针对表达式计算)
select avg(chinese + math + english) from exam_result;

执行结果:


group by 子句

  • 使用 group by 子句可以对指定列进行分组查询
  • 不使用 group by 分组的时候,就相当于只要一组,把所有的行进行聚合
  • 引入 group by 就可以针对不同的组,来分别进行聚合

实例理解

  • 此处我们创建一个 emp 表,并插入几条数据

                                         

  • 此处我们想根据 role 字段分别查询各个职位的平均薪水
select role,avg(salary) from emp group by role;

执行结果:


  • 分组查询 也是可以指定条件的

三种情况

  • 分组之前 指定条件,即先筛选再分组(where)
  • 分组之后 指定条件,即先分组再筛选(having)
  • 分组之前和之后,都指定条件

实例理解

  • 查询每个岗位的平均薪资,但是需筛选掉 employ 岗位中 name = haoran 的薪水
  • 使用 where
select role,avg(salary) from emp where name != 'haoran' group by role;

执行结果:

  • 查询每个岗位的平均薪水,但是最后筛选掉平均薪水大于 10000 的岗位
  • 使用 having

执行结果:

  • 查询每个岗位的平均薪资,但是在计算平均薪水之前 需筛选掉 employ 岗位中 name = haoran 的薪水,在计算平均薪水后 需筛选掉平均薪水大于 10000 的岗位
  • where 和 having 结合使用
select role,avg(salary) from emp where name != 'haoran' group by role having avg(salary) < 10000;

执行结果:


执行流程图

联合查询 

笛卡尔积

  • 多表查询的基本执行过程:笛卡尔积

实例理解一

  • 此处我们创建两个表,分别为 student 表 和 class 表,并插入几条数据

  • 此时我们想得到 student 表 和 class 表的笛卡尔积
select * from student, class;

执行结果:

  • 笛卡尔积得到一个更大的表列数为两个表列数之和行数为两个表行数之积
  • 但是仔细观察,笛卡尔积里的结果,很多都是无效数据,只有一部分是有意义的
  • 因此我们需要把 无意义的数据给筛选掉
  • 此处无意义的数据行为 classId 既为 1 又为 2 的
select * from student, class where student.classId = class.classId;

执行结果:

  • 加上条件后,我们所查询到的数据便都是合法的了
  • 此处我们将用来筛选有效数据的条件 称为连接条件


实例理解二

  • 此处我们创建四个表,分别为 classes 表、student 表、course 表、score 表,并插入多条数据

分析:

  • 学生 和 班级,一对多关系
  • 学生 和 课程,多对多关系要想表示这个多对多关系,就需要引入个关联表
  • score 表正好描述了 学生 和 课程 之间的关联关系,顺便也把分数也给列出来了

1)查询 许仙 同学的成绩

  • 先计算笛卡尔积,加上连接条件
select * from student,score where student.id = score.student_id;

执行结果:

  • 根据需求,我们仅需得到 name = '许仙' 的数据行
select * from student,score where student.id = score.student_id and name = '许仙';

执行结果:

  • 再针对查询的列进行精简,此处只保留 name 字段 和 score 字段
select student.name,score.score from student,score where student.id = score.student_id and name = '许仙';


2)使用 join 关键字查询 许仙 同学的成绩

  • 写法一
select student.name,score.score from student join score on student.id = score.student_id and student.name = '许仙';
  • 写法二
select student.name,score.score from student inner join score on student.id = score.student_id and student.name = '许仙';

执行结果:

  • 这两种写法的执行结果相同


注意:

  • 上述 直接 from 多个表和使用 join on 关键字,虽然均能实现查询许仙同学成绩
  • 但是 直接 from 多个表,只能实现 内连接
  • 而 join on 既可以实现 内连接 也能实现 外连接

3)查询所有同学的总成绩,及同学的个人信息

select student.name,sum(score.score) as '总分' from student,score where student.id = score.student_id group by student.name;

执行结果:


4)查询所有学生的成绩信息,及同学的个人信息

  • 期望查询结果中包含个人信息、课程名字、分数

写法一:

  • 直接 from 多个表
select student.name,course.name as course_name,score.score from student,course,score where student.id = score.student_id and score.course_id = course.id;

写法二:

  • 使用 join 关键字
select student.name,course.name as course_name,score.score from student join score on student.id = score.student_id join course on score.course_id = course.id;

执行结果:


内连接 外连接

  • 内连接 和 外连接在大多数情况下,是没区别的
  • 比如 要连接的两个表,其里面的数据都是相互对应的,这时候二者没区别
  • 如果不是 相互对应的,那么此时 内连接 和 外连接 就有区别了

实例理解一

  • 此处我们创建两个表,分别为 student 表 和 score 表,并插入多条数据
  • 此时我们两个表中的数据为 相互对应的

  • 使用 直接 from 多个表的方式 查询学生成绩
select * from student,score where student.id = score.student_id;

执行结果:

  • 使用 join 关键字的方式 查询学生成绩
select * from student join score on student.id = score.student_id;

执行结果:

  • 我们可以对比观察两种方式的查询结果,发现查询结果相同,且此处的连接为 内连接

实例理解二

  • 此处我们将 score 表中的 score = 70 的 student_id 改为 4
  • 此时 student 表中的 王五 同学是没有分数的
  •  score 表中 student_id = 4 的分数不知道是哪位同学的

  • 使用 直接 from 多个表的方式 查询学生成绩
select * from student,score where student.id = score.student_id;

执行结果:

  • 此处的查询结果为 两个表中能相互对应上的数据

  • 使用 join 关键字的方式 查询学生成绩
select * from student join score on student.id = score.student_id;

执行结果:

  • 此处的查询结果为 两个表中都有的数据,即能对应上的数据

  • 上述的两种写法均为 内连接

  • 此时我们通过 join 关键字来实现外连接
  • 写法为在 join 前面加个 left  或 right ,分别对应着 左外连接 和 右外连接

左外连接

select * from student left join score on student.id = score.student_id;

执行结果:

  • 左外连接 会把左表的结果尽量列出来,哪怕在右表中没有对应的记录,就使用 NULL 填充

右外连接

select * from student right join score on student.id = score.student_id;

执行结果:

  • 右外连接 会把右表的结果尽量列出来,哪怕在左表中没有对应的记录,就使用 NULL 填充


自连接

  • 自己和自己进行笛卡尔积
  • 自连接的效果就是把 行 转成 列
  • sql 中无法针对 行和行 之间使用条件比较
  • 但是有的需要中,又需要行和行比较,就可以使用 自连接 把行转成列

实例理解

  • 此处我们还是使用下图所示的四张表 举例说明


1)查询计算机原理成绩比 Java 高的同学 id

  • 首先我们进行笛卡尔积,并简单筛选 无效数据
select * from score as s1,score as s2 where s1.student_id = s2.student_id;

执行结果:

  • 插叙出来的数据行还是比较多的,此处我们仅截取 1号同学

分析:

  • 我们可以看到这里的每一行就是在针对同一个同学的各种课程 id 进行了排列组合
  • 同时也是针对分数进行 排列组合
  • 上图红框部分数据行 其 course_id 分别为 3 和 1,即代表 计算机原理 和 Java
  • 上图 红框部分 和 绿框部分 为重复行,所以我们还需进行去重
select * from score as s1,score as s2 where s1.student_id = s2.student_id and s1.course_id = 3 and s2.course_id = 1;

执行结果:

  • 此处我们再进一步指定查询 s1 表 course_id = 3 且 s2 表 course_id = 1 的数据行
  • 即 s1 表仅保留 计算机原理的成绩,s2 表仅保留 Java 的成绩
  • 既满足了 仅需比较 计算机原理 和 Java 这两门课的成绩的要求也达到了去重的目的

  • 最后我们再进行最后的筛选,只留下计算机原理成绩 比 Java 高 的数据行
select * from score as s1,score as s2 where s1.student_id = s2.student_id and s1.course_id = 3 and s2.course_id = 1 and s1.score > s2.score;

执行结果:


子查询

  • 子查询本质上就是套娃,即把多个 sql 组合成了一个
  • 在实际开发中,子查询要慎用
  • 因为子查询可能会构造出非常复杂、不好理解的 sql,对于 代码的可读性 和 sql的执行效率 很可能是毁灭性的打击

单行子查询

  • 返回一行记录的子查询

实例理解

  •  此处我们还是使用下图所示的四张表 举例说明

1)查询 name = '不想毕业' 的同班同学的姓名

  • 步骤一:先查询到 name = '不想毕业' 同学的班级 id
select classes_id from student where name = '不想毕业';

执行结果:

  • 步骤二:根据查询到的班级 id 来查询该班级的所有学生姓名,排除掉 name = '不想毕业' 同学
select name from student where classes_id = 1 and name != '不想毕业';

执行结果:

  • 我们子查询就是将上述的两个步骤合二为一
select name from student where classes_id = (select classes_id from student where name = '不想毕业') and name != '不想毕业';

执行结果:


多行子查询

  • 返回多行记录的子查询

实例理解

  • 还是使用上文 的四张表来举例

1)查询 语文 或 英语 课程的成绩信息

  • 步骤一:先根据名字 查询出课程 id
select id from course where name = '语文' or name = '英文';

执行结果:

  • 步骤二: 根据课程 id 查询出课程分数
select * from score where course_id in(4,6);

执行结果:

  • 使用子查询将上述两个步骤合并为一
select * from score where course_id in(select id from course where name = '语文' or name = '英文');

执行结果:


EXISTS 关键字

  • 该关键字的可读性比较差 且 执行效率也大大低于 in 关键字写法,但使用 exists 关键字可以解决一些特殊场景
  • 如 当我们使用 in 关键字进行查询时,其查询结果在内存中,如果查询结果太大,以至于内存都放不下了
  • 此时就不能使用 in 关键字,需转而使用 exists 关键字代替
  • 实际上处理上述场景 更推荐的是多步完成查询,没必要强行合成一个
  • exists 关键字的本质也就是让数据库执行多个 查询操作

合并查询

  • 本质上就是把两个查询的结果集 合并成一个
  • 要求这两个结果集的列相同才能合并即 列的类型 + 列的个数 + 列的名字 相同

实例理解:

  •  此处我们还是使用下图所示的四张表 举例说明

1)查询 id < 3 或者名字为 英文 的课程

  • 此处使用 union 关键字进行 合并查询
select * from course where id<3 union select * from course where name = '英文';

执行结果:

注意:

  • 虽然在该场景下使用 or 关键字也能完成查询
  • 但是用 or 关键字 时,你的查询只能来自于同一张表
  • 如果使用 union 关键字查询结果,你的查询可以来自于不同的表,只要保证查询结果的列相同即可

union on 和 union 的区别

  • union on 和 union 这两个关键字,在大多数场景下都是差不多的
  • 但 union 会进行去重操作,即重复的行只会保留一份
  • 而 union on 可以保留多份重复的数据行,不会去重

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/225443.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

人工智能与星际旅程:技术前沿与未来展望

人工智能与星际旅程&#xff1a;技术前沿与未来展望 一、引言 随着科技的飞速发展&#xff0c;人工智能&#xff08;AI&#xff09;在各个领域的应用越来越广泛。在星际旅程领域&#xff0c;AI也发挥着越来越重要的作用。本文将探讨人工智能与星际旅程的结合&#xff0c;以及…

[.NET开发者的福音]一个方便易用的在线.NET代码编辑工具.NET Fiddle

前言 今天给大家分享一个方便易用的.NET在线代码编辑工具&#xff0c;能够帮助.NET开发人员快速完成代码编写、测试和分享的需求&#xff08;.NET开发者的福音&#xff09;&#xff1a;.NET Fiddle。 .NET Fiddle介绍 我们可以不用再担心环境与庞大的IDE安装的问题&#xff0…

初识RabbitMq

目录 1.初识MQ1.1.同步调用1.2.异步调用1.3.技术选型 2.RabbitMQ2.1.安装2.2.收发消息2.2.1.交换机2.2.2.队列2.2.3.绑定关系2.2.4.发送消息 2.3.数据隔离2.3.1.用户管理2.3.2.virtual host 1.初识MQ 1.1.同步调用 之前说过&#xff0c;我们现在基于OpenFeign的调用都属于是同…

「构」向云端 - 我与 2023 亚马逊云科技 re:Invent 大会

授权声明&#xff1a;本篇文章授权活动官方亚马逊云科技文章转发、改写权&#xff0c;包括不限于在 亚马逊云科技开发者社区, 知乎&#xff0c;自媒体平台&#xff0c;第三方开发者媒体等亚马逊云科技官方渠道 2023年亚马逊AWS re:Invent大会宣布一项Amazon Q的创新项目&#x…

vmware安装Linux虚拟机设置固定IP地址

Linux虚拟机设置固定IP 近期工作需要&#xff0c;本地用VMware安装了三台Linux-centos虚拟机&#xff0c;来搭建rocketmq集群。但是IP地址每天关机重启之后就会比变化&#xff0c;很是恼火。找到了一个修改的教程&#xff0c;亲测有效&#xff01;&#xff01;&#xff01;&am…

Java生成带log的二维码

生成二维码案例 1.引入依赖 <!-- zxing生成二维码 --> <dependency><groupId>com.google.zxing</groupId><artifactId>core</artifactId><version>3.3.3</version> </dependency><dependency><groupId>co…

1.了解数据结构和算法

1.了解数据结构和算法 1.1 二分查找 二分查找&#xff08;Binary Search&#xff09;是一种在有序数组中查找特定元素的搜索算法。它的基本思想是将数组分成两半&#xff0c;然后比较目标值与中间元素的大小关系&#xff0c;从而确定应该在左半部分还是右半部分继续查找。这个…

前端自定义验证码,校验验证码,验证码时效

最近做的项目&#xff0c;不需要后端接口&#xff0c;只需要前端验证&#xff0c;如图 初始页面 获取验证码 验证码的文件&#xff0c;直接复制就行 <template><div class"s-canvas"><canvasid"s-canvas":width"contentWidth":…

HTML---列表.表格.媒体元素

文章目录 目录 文章目录 一.列表 无序列表 有序列表 自定义列表 二.表格 表格的兼并 三.媒体元素 视频标签 音频标签 四.内联框架 五.拓展标签 总结 一.列表 无序列表 HTML中的无序列表&#xff08;Unordered List&#xff09;用于显示一组项目&#xff0c;每个项目之前…

【Pytorch】Transposed Convolution

文章目录 1 卷积2 反/逆卷积3 MaxUnpool / ConvTranspose4 encoder-decoder5 可视化 学习参考来自&#xff1a; 详解逆卷积操作–Up-sampling with Transposed Convolution PyTorch使用记录 https://github.com/naokishibuya/deep-learning/blob/master/python/transposed_co…

每天五分钟计算机视觉:Inception网络是由多个Inception模块构成

本文重点 inception从另一种角度来提升训练结果:能更高效的利用计算资源,在相同的计算量下能提取到更多的特征,从而提升训练结果。可以简单的理解为Inception 网络是由一个一个的Inception模块构建成的,我们来看一下。 Inception模块 如上就是Inception模块的 通过一个1…

采埃孚4D成像雷达拆解

1 基本信息 品牌&#xff1a;海外Tier1采埃孚 • 应用&#xff1a;上汽飞凡中高端纯电平台 • 数量&#xff1a;单车2个&#xff0c;安装在前后保内部 • 最远探测距离&#xff1a;350米 拆解来看&#xff0c;4D雷达主要可以分为4个部分&#xff0c;分别为数字接口板及结构件…

JAVA对文档加密

当 Word 文档中包含无法公开的机密信息时&#xff0c;我们可以对其进行加密&#xff0c;使其在没有密码的情况下无法打开。本文将向您介绍如何使用 Spire.Doc for Java 加密 Word 文档和移除 Word 密码保护。 加密 Word 文档删除 Word 密码保护 安装 Spire.Doc for Java 首先…

eclipse连接mysql数据库(下载eclipse,下载安装mysql,下载mysql驱动)

前言&#xff1a; 使用版本&#xff1a;eclipse2017&#xff0c;mysql5.7.0&#xff0c;MySQL的jar建议使用最新的&#xff0c;可以避免警告&#xff01; 1&#xff1a;下载安装&#xff1a;eclipse&#xff0c;mysql在我之前博客中有 http://t.csdnimg.cn/UW5fshttp://t.csdn…

云上丝绸之路| 云轴科技ZStack成功实践精选(西北)

古有“丝绸之路” 今有丝绸之路经济带 丝路焕发新生&#xff0c;数智助力经济 云轴科技ZStack用“云”护航千行百业 沿丝绸之路&#xff0c;领略西北数字化。 古丝绸之路起点-陕西 集历史与现代交融&#xff0c;不仅拥有悠久的历史文化积淀&#xff0c;而且现代化、数字化发…

【setDS】牛客小白月赛83 E

登录—专业IT笔试面试备考平台_牛客网 题意 思路 首先&#xff0c;一个必要步骤是把它转化为两个序列&#xff0c;这样就变成了一个序列DS问题 我们的答案是一个位置 pos 后面还有多少位置和这个位置的颜色相同&#xff0c;考虑得到这个答案我们需要维护什么东西 我们只需要…

Jmeter,提取响应体中的数据:正则表达式、Json提取器

一、正则表达式 1、线程组--创建线程组&#xff1b; 2、线程组--添加--取样器--HTTP请求&#xff1b; 3、Http请求--添加--后置处理器--正则表达式提取器&#xff1b; 4、线程组--添加--监听器--查看结果树&#xff1b; 5、线程组--添加--取样器--调试取样器。 响应体数据…

Axure动态面板的使用以及示例分享

目录 一. 什么是动态面板 二. 动态面板教程——以轮播图为例 2.1 创建动态面板 2.2 动态面板自适应大小 2.3 重复状态&#xff0c;将图片导入 2.4 添加交互事件——图片切换 2.5 效果展示 三. 多方式登录示例展示 四. 后台主界面左侧菜单栏示例展示 一. 什么是动态面板…

【C语言】C的面向对象

一、BREW接口实现 高通的BREW&#xff08;Binary Runtime Environment for Wireless&#xff09;是一个早期为手机设备开发的应用程序平台&#xff0c;用于开发在CDMA手机上运行的软件。尽管这个平台目前已经不太流行&#xff0c;但是在其使用高峰时期&#xff0c;开发者需要使…

vue2 tailwindcss jit模式下热更新失效

按照网上教程安装的tailwindcss&#xff0c;但是修改类名后热更新的时候样式没有生效&#xff0c;参考了大佬的文章&#xff0c;解决了该问题。 安装cross-env 修改前 "dev": " vue-cli-service serve", 修改后 "dev": "cross-env TAILWIN…