MySQL复合查询

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
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



注意:


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

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


相关实践学习
基于CentOS快速搭建LAMP环境
本教程介绍如何搭建LAMP环境,其中LAMP分别代表Linux、Apache、MySQL和PHP。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
2天前
|
存储 关系型数据库 MySQL
MySQL查询:过滤掉字母
【5月更文挑战第5天】
|
2天前
|
存储 算法 关系型数据库
MySQL怎样处理排序⭐️如何优化需要排序的查询?
MySQL怎样处理排序⭐️如何优化需要排序的查询?
|
2天前
|
SQL 关系型数据库 MySQL
MySQL数据库的约束+进阶版新增与查询-2
MySQL数据库的约束+进阶版新增与查询
14 1
|
2天前
|
关系型数据库 MySQL 测试技术
MySQL数据库的约束+进阶版新增与查询-1
MySQL数据库的约束+进阶版新增与查询
16 1
|
2天前
|
SQL 存储 关系型数据库
MySQL查询原理,看这一篇就够了!
MySQL查询原理,看这一篇就够了!
|
2天前
|
SQL 关系型数据库 MySQL
MySQL 基本概念 基础用法 增删改查(特殊查询)语法 详细篇
MySQL 基本概念 基础用法 增删改查(特殊查询)语法 详细篇
|
2天前
|
缓存 关系型数据库 MySQL
为什么MySQL分页查询偏移量越大查询越慢
【5月更文挑战第1天】为什么MySQL分页查询偏移量越大查询越慢
50 4
|
2天前
|
SQL 关系型数据库 MySQL
【MySQL】DQL-排序查询-语法&注意事项&可cv例题语句
【MySQL】DQL-排序查询-语法&注意事项&可cv例题语句
|
2天前
|
SQL 关系型数据库 MySQL
【MySQL】DQL-排序查询-语法&排序方式&注意事项&可cv例题语句
【MySQL】DQL-排序查询-语法&排序方式&注意事项&可cv例题语句
|
2天前
|
SQL 关系型数据库 MySQL
【MySQL】DQL-分组查询-语法&where与having的区别&注意事项&可cv例题语句
【MySQL】DQL-分组查询-语法&where与having的区别&注意事项&可cv例题语句
【MySQL】DQL-分组查询-语法&where与having的区别&注意事项&可cv例题语句

推荐镜像

更多