MySQL复合查询

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS PostgreSQL,高可用系列 2核4GB
RDS MySQL Serverless 高可用系列,价值2615元额度,1个月
简介: 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 
目录
相关文章
|
2月前
|
SQL 人工智能 关系型数据库
如何实现MySQL百万级数据的查询?
本文探讨了在MySQL中对百万级数据进行排序分页查询的优化策略。面对五百万条数据,传统的浅分页和深分页查询效率较低,尤其深分页因偏移量大导致性能显著下降。通过为排序字段添加索引、使用联合索引、手动回表等方法,有效提升了查询速度。最终建议根据业务需求选择合适方案:浅分页可加单列索引,深分页推荐联合索引或子查询优化,同时结合前端传递最后一条数据ID的方式实现高效翻页。
130 0
|
23天前
|
存储 关系型数据库 MySQL
使用命令行cmd查询MySQL表结构信息技巧分享。
掌握了这些命令和技巧,您就能快速并有效地从命令行中查询MySQL表的结构信息,进而支持数据库维护、架构审查和优化等工作。
150 9
|
3月前
|
关系型数据库 MySQL 数据库
MySQL报错:未知系统变量'tx_isolation'及隔离级别查询
记住,选择合适的隔离级别,就像是在风平浪静的湖面上找到适合的划船速度——既要快到能赶上午饭(性能),又不至于翻船(数据一致性问题)。
185 3
|
3月前
|
SQL 关系型数据库 MySQL
MySQL 进行 select 查询时 where 条件中 in 的value数过多却导致无记录返回
MySQL 进行 select 查询时 where 条件中 in 的value数过多返回不符合预期怎么办?会不会遇到bug了?
197 0
|
4月前
|
缓存 JSON 关系型数据库
MySQL 查询优化分析 - 常用分析方法
本文介绍了MySQL查询优化分析的常用方法EXPLAIN、Optimizer Trace、Profiling和常用监控指标。
|
7月前
|
算法 关系型数据库 MySQL
join查询可以⽆限叠加吗?MySQL对join查询有什么限制吗?
大家好,我是 V 哥。本文详细探讨了 MySQL 中 `JOIN` 查询的限制及其优化方法。首先,`JOIN` 查询不能无限叠加,存在资源(CPU、内存、磁盘 I/O)、性能和语法等方面的限制。过多的 `JOIN` 操作会导致数据库性能急剧下降。其次,介绍了三种常见的 `JOIN` 查询算法:嵌套循环连接(NLJ)、索引嵌套连接(INL)和基于块的嵌套循环连接(BNL),并分析了它们的触发条件和性能特点。最后,分享了优化 `JOIN` 查询的方法,包括 SQL 语句优化、索引优化、数据库配置调整等。关注 V 哥,了解更多技术干货,点赞👍支持,一起进步!
147 3
|
9月前
|
SQL 关系型数据库 MySQL
【MySQL基础篇】多表查询(隐式/显式内连接、左/右外连接、自连接查询、联合查询、标量/列/行/表子查询)
本文详细介绍了MySQL中的多表查询,包括多表关系、隐式/显式内连接、左/右外连接、自连接查询、联合查询、标量/列/行/表子查询及其实现方式,一文全面读懂多表联查!
【MySQL基础篇】多表查询(隐式/显式内连接、左/右外连接、自连接查询、联合查询、标量/列/行/表子查询)
|
8月前
|
缓存 关系型数据库 MySQL
【深入了解MySQL】优化查询性能与数据库设计的深度总结
本文详细介绍了MySQL查询优化和数据库设计技巧,涵盖基础优化、高级技巧及性能监控。
1472 1
|
9月前
|
SQL 关系型数据库 MySQL
MySQL 窗口函数详解:分析性查询的强大工具
MySQL 窗口函数从 8.0 版本开始支持,提供了一种灵活的方式处理 SQL 查询中的数据。无需分组即可对行集进行分析,常用于计算排名、累计和、移动平均值等。基本语法包括 `function_name([arguments]) OVER ([PARTITION BY columns] [ORDER BY columns] [frame_clause])`,常见函数有 `ROW_NUMBER()`, `RANK()`, `DENSE_RANK()`, `SUM()`, `AVG()` 等。窗口框架定义了计算聚合值时应包含的行。适用于复杂数据操作和分析报告。
401 11
|
9月前
|
存储 Oracle 关系型数据库
索引在手,查询无忧:MySQL索引简介
MySQL 是一款广泛使用的关系型数据库管理系统,在2024年5月的DB-Engines排名中得分1084,仅次于Oracle。本文介绍MySQL索引的工作原理和类型,包括B+Tree、Hash、Full-text索引,以及主键、唯一、普通索引等,帮助开发者优化查询性能。索引类似于图书馆的分类系统,能快速定位数据行,极大提高检索效率。
151 8

推荐镜像

更多