MySQL复合查询

本文涉及的产品
RDS MySQL DuckDB 分析主实例,集群系列 4核8GB
RDS MySQL DuckDB 分析主实例,基础系列 4核8GB
RDS AI 助手,专业版
简介: MySQL复合查询

一、多表查询

实际开发中往往需要将多张表关联起来进行查询,即多表查询

在进行多表查询时,只需将多张表的表名依次放到from子句后,用逗号隔开即可。MySQL将会对给定的这多张表取笛卡尔积,作为多表查询的初始数据源

多表查询的本质,就是对给定的多张表取笛卡尔积,然后在笛卡尔积中进行查询

对多张表取笛卡尔积,即得到这多张表的记录的所有可能有序对组成的集合,如下面对员工表和部门表进行多表查询,由于查询语句中没有指明筛选条件,因此最终得到的结果便是员工表和部门表的笛卡尔积

438aeadfe53f43b7a61b89752f975373.png



员工表和部门表的笛卡尔积由两部分组成,前半部分是员工表的列信息,后半部分是部门表的列信息

对员工表和部门表取笛卡尔积时,会先从员工表中选出一条记录与部门表中的所有记录进行组合,然后再从员工表中选出一条记录与部门表中的所有记录进行组合,以此类推,最终得到的就是这两张表的笛卡尔积

笛卡尔积的初步过滤


对多张表取笛卡尔积后得到的数据并不都是有意义的,如对员工表和部门表取笛卡尔积时,员工表中的每一个员工信息都会和部门表中的每一个部门信息进行组合,而实际一个员工只有和自己所在的部门信息进行组合才是有意义的,因此需要从笛卡尔积中筛选出员工的部门号和部门的编号相等记录

50a746b4fdd648d999ebfcf4f8d8f48d.png



注意:进行笛卡尔积的多张表中可能会存在相同的列名,在选中列名时需通过 表名.列名 的方式指明


显示部门号为10的部门名、员工名和员工工资


由于部门名仅在部门表中,而员工名和员工工资仅在员工表中,因此需同时使用员工表和部门表进行多表查询,在where子句中指明筛选条件为员工的部门号等于部门编号,并且部门号为10的记录


4e9be9096bb84ea19ef25acf1e1da650.png


显示各个员工的姓名、工资和工资级别


员工名和工资仅在员工表中,工资级别仅在工资等级表中,因此需同时使用员工表和工资等级表进行多表查询,在where子句中指明筛选条件为员工的工资在losal和hisal之间的记录


c35083ab83cd4b04acad243840ad65c0.png


员工表和工资等级表的笛卡尔积中,将每一个员工的信息和每一个工资等级的信息都进行了组合,而实际一个员工只有和自己的工资对应的工资等级信息组合才有意义

因此需要根据各个工资等级的最低工资和最高工资判断一个员工是否属于该工资等级,进而筛选出有意义的记录

二、自连接

概念


自连接是指在同一张表进行连接查询,即不仅可以取不同表的笛卡尔积,也可以对同一张表取笛卡尔积

若一张表中的某个字段能够将表中的多条记录关联起来,那么就可以通过自连接将表中通过该字段关联的记录组合起来

显示员工FORD的上级领导的编号和姓名


解决该问题可使用子查询,先对员工表查询得到FORD的领导的编号,然后再根据领导的编号对员工表进行查询得到FORD领导的姓名


b68f3af8cd7b435e9619dea736b83c4b.png


也可使用自连接解决该问题,因为员工表中的mgr字段能够将表中员工的信息和员工领导的信息关联起来

e65ca6137e754ee39d88814425775b41.png



员工表进行自连接后,在where子句中指明筛选条件为员工的领导编号等于领导的编号,这时就能筛选出每个员工信息与其领导信息组合形成的记录,进一步指明筛选条件为员工的姓名为FORD,这时便能筛选出员工FORD的信息和他的领导的信息组成的记录


dba631866e53465dbbc33754e87af5e6.png


注意: 自连接是对同一张表取笛卡尔积,因此在自连接时至少需给一张表取别名,否则无法区分这两张表中的列


三、子查询

3.1 单行子查询

单行子查询,即返回单行单列数据(唯一数据)的子查询


显示SMITH同一部门的员工


在子查询中查询SMITH所在的部门号,在where子句中指明筛选条件为员工部门号等于子查询返回的部门号,并且员工的姓名不为SMITH

c2234a83aa8940ab83baccdfe08e5740.png



也可以使用自连接解决该问题,因为和SMITH同一部门的员工的信息也在员工表中,因此对员工表进行自连接后,在where子句中指明表1的员工姓名为SMITH,并且表1和表2的部门号必须相等,并且表2的员工姓名不为SMITH,这样也能筛选出和SMITH同一部门的员工信息

71ad55afaf82421baac5d6f9e26f0c69.png



3.2 多行子查询

多行子查询,即返回多行数据(集合)的子查询


in关键字:显示和10号部门的工作岗位相同的员工的名字、岗位、工资和部门号,但是不包含10号部门的员工


先查询10号部门有哪些工作岗位,在查询时最好对结果进行去重,因为10号部门的某些员工的工作岗位可能是相同的


61571651b82f4aa4b7b1b047f3c80fc1.png


将上述查询作为子查询,在查询员工表时在where子句中使用in关键字,判断员工的工作岗位是子查询得到的若干岗位中的一个,若是则符合筛选条件,由于要求筛选出来的员工不包含10号部门的,因此还需要在where子句中指明筛选条件为部门号不等于10


7858d4eb8c4f416f8dfde6a146fbbf79.png


all关键字:显示工资比30号部门的所有员工的工资高的员工的姓名、工资和部门号


先查询30号部门员工的工资,在查询时最好对结果进行去重,因为30号部门的某些员工的工资可能是相同的


cf8717cef5a343d3b78dd6b0cd233cf4.png


将上述查询作为子查询,在where子句中使用all关键字,判断员工的工资是否高于子查询得到的所有工资,若是则符合筛选条件


11e4517f3e62468e84ec88ed978f66f1.png


这道题等价于找到工资高于30号部门的最高工资的员工,也可使用单行子查询得到30号部门的最高工资,然后判断员工的工资是否高于子查询得到的最高工资即可


9bc2a6fa453145908526305f51451c4d.png


any关键字:显示工资比30号部门的任意员工的工资高的员工的姓名、工资和部门号,包含30号部门的员工


先查询30号部门员工的工资,然后在查询员工表时在where子句中使用any关键字,判断员工的工资是否高于子查询的得到的工资中的某一个,若是则符合筛选条件

b573e444c9524f2d9957bbfe6352d007.png



这道题也等价于找到工资高于30号部门的最低工资的员工,因此也可以使用单行子查询得到30号部门的最低工资,然后判断员工的工资是否高于子查询得到的最低工资即可,由于要求筛选出来的员工包含30号部门的,因此不需要再对部门号进行过滤


0bac61c582a64b5b9d733d1f0f0cd18f.png


3.3 多列子查询

多列子查询,即返回多列数据的子查询


显示和SMITH的部门和岗位完全相同的员工,不包含SMITH本人


先查询SMITH所在部门的部门号和其岗位,将其作为子查询

5bcc13c68b64444f870f80698499d7a6.png



在查询员工表时在where子句中,指明筛选条件为部门号和岗位等于子查询得到的部门号和岗位,并且员工的姓名不为SMITH即可

eddbec45752549e4a17f1b5d4733eb76.png



注意:


多列子查询得到的结果是多列数据,在比较多列数据时需要将待比较的多个列用圆括号括起来

多列子查询返回的若是多行数据,在筛选数据时也可以使用in、all和any关键字

3.4 在from子句中使用子查询

子查询语句不仅可以出现在where子句中,也可出现在from子句中

子查询语句出现from子句中,其查询结果将会被当作一个临时表使用

显示每个高于自己部门平均工资的员工的姓名、部门、工资和部门的平均工资


首先查询每个部门的平均工资


dbd411185cd748218f77889d7d056458.png


显示信息中包含部门的平均工资,需同时使用员工表和上述的查询结果进行多表查询,这时可将上述查询作为子查询放在from子句中,然后对员工表和临时表取笛卡尔积,在where子句中指明筛选条件为员工的部门号等于临时表中的部门号,并且员工的工资大于临时表中的平均工资


bf4b8767ac3148ada1d0ef406f8a3d11.png


注意:在from子句中使用子查询时,必须给子查询得到的临时表取一个别名,否则查询将会出错


显示每个部门的部门名、部门编号、所在地址和人员数量


group by子句中指明按照部门号进行分组,分别查询每个部门的人员数量


c37d7b5972524b8dacc48ae9669f3e42.png


将上述查询作为子查询放在from子句中,然后对员工表和临时表取笛卡尔积,在where子句中指明筛选条件为员工的部门号等于临时表中的部门号即可


df8cd962f2a34807bc41ce52275c967c.png


除了上述子查询+多表查询的方式外,也可以只使用多表查询解决该问题


先对员工表和部门表取笛卡尔积

在where子句中指明筛选条件为员工的部门号等于部门的编号,筛选出有意义的记录

在group by子句中指明按照部门号进行分组,分别统计出每个部门的人数

d5116efe90524a1a973aa389ff5dd986.png


但由于题目同时要求显示每个部门的部门名和所在地址,因此在group by子句中需要添加按照部门名和地址进行分组


336a32c756044a2fbb27477dada6ca3b.png


在select语句中新增了要显示部门名和所在地址,因此需在group by子句中也添加这两个字段,表明当部门号相同时按照部门名进行分组,当部门名也相同时继续按照所在地址进行分组

但实际在上述场景中部门号相同的记录,它们的部门名和所在地址也一定是相同的(MySQL并不知道),因此在我们看来group by中继续添加这两个字段没什么意义,但MySQL语句要求必须添加

四、合并查询

合并查询,是指将多个查询结果进行合并,可使用的操作符有union和union all


union用于取得两个查询结果的并集,union会自动去掉结果集中的重复行

union all也用于取得两个查询结果的并集,但union all不会去掉结果集中的重复行

显示工资大于2500或职位是MANAGER的员工


查询工资大于2500的员工的SQL如下


e6fc1b4c61fd4b83929406a29f02bae7.png


查询职位是MANAGER的员工的SQL如下


712572c1011a4474b52c66682a1f90c3.png


可以使用union操作符将上述的两条查询SQL连接起来,这时将会得到两次查询结果的并集,并且会对合并后的结果进行去重


f559f4f9bb46480b80d748d28412a583.png


使用union all操作符将上述的两条查询SQL连接起来,这时将也会得到两次查询结果的并集,但不会对合并后的结果进行去重

5d7b2834bd9d45149997668a23682c0b.png



注意:


待合并的两个查询结果的列的数量必须一致,否则无法合并

待合并的两个查询结果对应的列属性可以不一样,但不建议这样做


相关实践学习
每个IT人都想学的“Web应用上云经典架构”实战
本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
MySQL数据库入门学习
本课程通过最流行的开源数据库MySQL带你了解数据库的世界。   相关的阿里云产品:云数据库RDS MySQL 版 阿里云关系型数据库RDS(Relational Database Service)是一种稳定可靠、可弹性伸缩的在线数据库服务,提供容灾、备份、恢复、迁移等方面的全套解决方案,彻底解决数据库运维的烦恼。 了解产品详情: https://www.aliyun.com/product/rds/mysql 
目录
相关文章
|
6月前
|
SQL 缓存 监控
MySQL缓存机制:查询缓存与缓冲池优化
MySQL缓存机制是提升数据库性能的关键。本文深入解析了MySQL的缓存体系,包括已弃用的查询缓存和核心的InnoDB缓冲池,帮助理解缓存优化原理。通过合理配置,可显著提升数据库性能,甚至达到10倍以上的效果。
|
6月前
|
SQL 存储 关系型数据库
MySQL体系结构详解:一条SQL查询的旅程
本文深入解析MySQL内部架构,从SQL查询的执行流程到性能优化技巧,涵盖连接建立、查询处理、执行阶段及存储引擎工作机制,帮助开发者理解MySQL运行原理并提升数据库性能。
|
8月前
|
SQL 人工智能 关系型数据库
如何实现MySQL百万级数据的查询?
本文探讨了在MySQL中对百万级数据进行排序分页查询的优化策略。面对五百万条数据,传统的浅分页和深分页查询效率较低,尤其深分页因偏移量大导致性能显著下降。通过为排序字段添加索引、使用联合索引、手动回表等方法,有效提升了查询速度。最终建议根据业务需求选择合适方案:浅分页可加单列索引,深分页推荐联合索引或子查询优化,同时结合前端传递最后一条数据ID的方式实现高效翻页。
427 0
|
6月前
|
SQL 关系型数据库 MySQL
MySQL的查询操作语法要点
储存过程(Stored Procedures) 和 函数(Functions) : 储存过程和函数允许用户编写 SQL 脚本执行复杂任务.
276 14
|
6月前
|
SQL 关系型数据库 MySQL
MySQL的查询操作语法要点
以上概述了MySQL 中常见且重要 的几种 SQL 查询及其相关概念 这些知识点对任何希望有效利用 MySQL 进行数据库管理工作者都至关重要
166 15
|
6月前
|
SQL 监控 关系型数据库
SQL优化技巧:让MySQL查询快人一步
本文深入解析了MySQL查询优化的核心技巧,涵盖索引设计、查询重写、分页优化、批量操作、数据类型优化及性能监控等方面,帮助开发者显著提升数据库性能,解决慢查询问题,适用于高并发与大数据场景。
|
6月前
|
SQL 关系型数据库 MySQL
MySQL入门指南:从安装到第一个查询
本文为MySQL数据库入门指南,内容涵盖从安装配置到基础操作与SQL语法的详细教程。文章首先介绍在Windows、macOS和Linux系统中安装MySQL的步骤,并指导进行初始配置和安全设置。随后讲解数据库和表的创建与管理,包括表结构设计、字段定义和约束设置。接着系统介绍SQL语句的基本操作,如插入、查询、更新和删除数据。此外,文章还涉及高级查询技巧,包括多表连接、聚合函数和子查询的应用。通过实战案例,帮助读者掌握复杂查询与数据修改。最后附有常见问题解答和实用技巧,如数据导入导出和常用函数使用。适合初学者快速入门MySQL数据库,助力数据库技能提升。
|
7月前
|
存储 关系型数据库 MySQL
使用命令行cmd查询MySQL表结构信息技巧分享。
掌握了这些命令和技巧,您就能快速并有效地从命令行中查询MySQL表的结构信息,进而支持数据库维护、架构审查和优化等工作。
626 9
|
6月前
|
SQL 监控 关系型数据库
MySQL高级查询技巧:子查询、联接与集合操作
本文深入解析了MySQL高级查询的核心技术,包括子查询、联接和集合操作,通过实际业务场景展示了其语法、性能差异和适用场景,并提供大量可复用的代码示例,助你从SQL新手进阶为数据操作高手。
|
8月前
|
人工智能 Java 关系型数据库
Java的时间处理与Mysql的时间查询
本文总结了Java中时间与日历的常用操作,包括时间的转换、格式化、日期加减及比较,并介绍了MySQL中按天、周、月、季度和年进行时间范围查询的方法,适用于日常开发中的时间处理需求。
151 0