2023.12.13 关于 MySQL 复杂查询

news2024/9/24 5:22:49

目录

聚合查询

聚合函数

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.coloradmin.cn/o/1313024.html

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

相关文章

wpf TelerikUI使用DragDropManager

首先&#xff0c;我先创建事务对象ApplicationInfo&#xff0c;当暴露出一对属性当例子集合对于构成ListBoxes。这个类在例子中显示如下代码&#xff1a; public class ApplicationInfo { public Double Price { get; set; } public String IconPath { get; set; } public …

【【ZYNQ 7020显示 图片 实验 】】

ZYNQ 7020显示 图片 实验 关键配置 BRAM 因为本次 我想显示的 图片是 400*400 所以在 内部 的 ROM 存储单元选择 了160000 ZYNQ7020的内部资源 最多是 大概 200000左右的 大小 大家可以根据 资源选择合适的像素 此处存放 内部的 图片转文字的COE文件 PLL设置 我选用的是按…

详解wmvcore.dll丢失的解决方法

wmvcore.dll是一款由Microsoft开发的Windows系统文件&#xff0c;主要用于存储和处理多媒体文件&#xff0c;尤其是Windows媒体视频。该文件对于音频和视频的播放至关重要。如果电脑上缺少这个文件&#xff0c;可能会出现播放问题或者相关的应用程序运行错误。在本文中&#xf…

Netty详解

目录标题 1、前期知识科普1.1 NIO 基本概念1.2 java BIO与NIO对比1.3 Reactor 模型 2、Netty 基础概念2.1 Netty 简介2.2 Netty 执行流程2.3 Netty 核心组件 3、Netty Demo编写3.1 总体框架3.2 具体代码 4、交流群 1、前期知识科普 1.1 NIO 基本概念 阻塞&#xff08;Block&a…

0x21 树与图的遍历

0x21 树与图的遍历 树与图最常见的储存方式就是使用一个邻接表保存它们的边集。邻接表以head数组为表头&#xff0c;使用ver和edge数组分别存储边的终点和权值&#xff0c;使用next数组模拟链表指针&#xff08;就像我们在0x13节中讲解邻接表所给出的代码那样&#xff09;。 …

科技铸就企业转型钢筋铁骨,群硕获评2023年度数字化影响力企业

12月15日&#xff0c;STIF2023第四届国际科创节暨DSC2023国际数字服务大会在北京顺利举行&#xff0c;本次大会以“数实融合 推动高质量发展”为主题&#xff0c;各大科技服务企业齐聚一堂&#xff0c;共同探讨2023科技发展新趋势。 大会上&#xff0c;群硕软件继2022年后再度…

Java版商城:Spring Cloud+SpringBoot b2b2c实现多商家入驻、直播带货及免 费小程序商城搭建

1. 涉及平台 平台管理、商家端&#xff08;pc端、手机端&#xff09;、买家平台&#xff08;h5/公众号、小程序、app端&#xff08;ios/android&#xff09;、微服务平台&#xff08;业务服务&#xff09; 2. 核心架构 spring cloud、spring boot、mybatis、redis 3. 前端框架…

如何远程访问Axure RP制作的本地web站点实现协同办公

文章目录 前言1.在AxureRP中生成HTML文件2.配置IIS服务3.添加防火墙安全策略4.使用cpolar内网穿透实现公网访问4.1 登录cpolar web ui管理界面4.2 启动website隧道4.3 获取公网URL地址4.4. 公网远程访问内网web站点4.5 配置固定二级子域名公网访问内网web站点4.5.1创建一条固定…

浅析AI视频分析与视频管理系统EasyCVR平台及场景应用

人工智能的战略重要性导致对视频智能分析的需求不断增加。鉴于人工智能视觉技术的巨大潜力&#xff0c;人们的注意力正在从传统的视频监控转移到计算机视觉的监控过程自动化。 1、什么是视频分析&#xff1f; 视频分析或视频识别技术&#xff0c;是指从视频片段中提取有用信息…

java.lang.UnsupportedOperationException

一、背景 记录一次小坑… 最近在写一个关于Excel导出的小需求&#xff0c;由于系统都有一些工具类&#xff0c;还有原来已经做好的导出&#xff0c;直接拿过来改了改就用了&#xff0c;没想到直接报错&#xff0c;尴尬。 还是那句话&#xff0c;别人都能用&#xff0c;我复制…

innovus:ccopt_design流程

我正在「拾陆楼」和朋友们讨论有趣的话题&#xff0c;你⼀起来吧&#xff1f; 拾陆楼知识星球入口 ccopt完整的流程包括如下几个步骤&#xff1a; spec文件可以只创建一次&#xff0c;无需多次创建。 1&#xff09;clustering阶段 set_ccopt_property balance_mode cluster …

产品经理之Axure的元件库使用详细案例

⭐⭐ 产品经理专栏&#xff1a;产品专栏 ⭐⭐ 个人主页&#xff1a;个人主页 ​ 目录 前言 一.Axure的元件库的使用 1.1 元件介绍 1.2 基本元件的使用 1.2.1 矩形、按钮、标题的使用 1.2.2 图片及热区的使用 1.3 表单元件及表格元件的使用 1.3.1表单元件的使用 1.3.…

NFS|在linux环境下的安装和配置NFS

简介 NFS全称网络文件系统&#xff0c;可用于不同服务器之间的文件共享。 接下来介绍下NFS在linux环境下安装和配置。主要分为服务端和客户端。 服务端安装 开启rpcbind/portmap和nfs服务 # service portmaper start [rootlocalhost java]# service portmap start Redirectin…

低代码平台浅析:引迈JNPF

低代码平台能够改变应用交付和管理的模式&#xff0c;大幅缩减交付周期&#xff0c;最终帮助业务加速创新。引迈JNPF作为当中的一个低代码平台&#xff0c;其在用户体系方面做得怎样呢&#xff1f;我针对引迈JNPF进行了相关体验与测评&#xff0c;一起来看下。 低代码平台体验简…

SpringBoot Starter机制 ——自动化配置

目录 一、Starter机制 1.1 什么是 SpringBoot Starter 1.2 SpringBoot Starter 的作用 1.3 Starter的应用场景 二、案例 2.1 模拟短信发送模版 2.2 AOP实现日志切面模版 一、Starter机制 1.1 什么是 SpringBoot Starter Spring Boot Starter是Spring Boot框架提供的一种…

[Linux] LVS负载均衡群集+NAT部署

一、LVS负载均衡群集知识 1.1 群集的的定义及意义 Cluster&#xff0c;集群&#xff08;也称群集&#xff09;由多台主机构成&#xff0c;但对外只表现为一一个整体&#xff0c;只提供一-个访问入口(域名或IP地址)&#xff0c; 相当于一台大型计算机。 群集的作用&#xff1…

upload-labs笔记

简介 upload-labs是一个使用php语言编写的&#xff0c;专门收集渗透测试和CTF中遇到的各种上传漏洞的靶场。旨在帮助大家对上传漏洞有一个全面的了解。目前一共21关&#xff0c;每一关都包含着不同上传方式。 文件上传漏洞是指&#xff1a; Web 服务器允许用户将文件上传至其…

使用blip2进行图片输入文本输出

多模态的重要模型blip2,官方提供模型可以直接用来图片生成文本 github地址&#xff1a;https://github.com/salesforce/LAVIS/tree/main/projects/blip2 个人相当于跑了一下blip2的demo&#xff0c;记录下过程&#xff0c;供今后需要参考&#xff1a; 1、首先是环境安装&#…

Spring上下文之注解模块ConfigurationMethod

博主介绍:✌全网粉丝5W+,全栈开发工程师,从事多年软件开发,在大厂呆过。持有软件中级、六级等证书。可提供微服务项目搭建与毕业项目实战,博主也曾写过优秀论文,查重率极低,在这方面有丰富的经验✌ 博主作品:《Java项目案例》主要基于SpringBoot+MyBatis/MyBatis-plus+…

如何实现免费的文档翻译

文中有彩蛋&#xff0c;请一定要看完。 目录 文中有彩蛋&#xff0c;请一定要看完。 一、问题的提出 二、文档翻译现状 三、如何免费海量文档翻译 1. 采用CAT工具机器翻译API法 2. 采用小牛文档翻译 四、学后反思 一、问题的提出 随着互联网和人工智能技术的飞速发展&…