MySQL数据库:复合查询

目录

一. 多表查询

二. 子查询

2.1 单行子查询

2.2 多行子查询

2.3 多列子查询

2.4 在from语句中使用子查询

三. 合并查询

3.1 union

3.2 union all

四. 总结


前置说明:本文主要oracle 9i的经典雇员信息测试表为例,进行示例演示。

该表有三个子表构成,分别为:(1). dept -- 部门信息表、(2). emp -- 雇员信息表 、(3). salgrade -- 薪资等级表,下面是每张表的desc字段及属性信息:

  • dept的字段信息包括:deptno -- 部门编号、dname -- 部门名称、loc -- 部门地点。
  • emp的字段信息包括:empno -- 员工编号、ename -- 员工姓名、job -- 工种、mgr -- 直属领导工号、hiredate -- 雇佣时间、sal -- 薪资、comm -- 绩效奖金、deptno -- 所属部门号。
  • salgrade的字段信息:grade -- 薪资等级、losal -- 最低薪资、hisal -- 最高薪资。
mysql> desc dept;
+--------+--------------------------+------+-----+---------+-------+
| Field  | Type                     | Null | Key | Default | Extra |
+--------+--------------------------+------+-----+---------+-------+
| deptno | int(2) unsigned zerofill | NO   |     | NULL    |       |
| dname  | varchar(14)              | YES  |     | NULL    |       |
| loc    | varchar(13)              | YES  |     | NULL    |       |
+--------+--------------------------+------+-----+---------+-------+
3 rows in set (0.00 sec)

mysql> desc emp;
+----------+--------------------------+------+-----+---------+-------+
| Field    | Type                     | Null | Key | Default | Extra |
+----------+--------------------------+------+-----+---------+-------+
| empno    | int(6) unsigned zerofill | NO   |     | NULL    |       |
| ename    | varchar(10)              | YES  |     | NULL    |       |
| job      | varchar(9)               | YES  |     | NULL    |       |
| mgr      | int(4) unsigned zerofill | YES  |     | NULL    |       |
| hiredate | datetime                 | YES  |     | NULL    |       |
| sal      | decimal(7,2)             | YES  |     | NULL    |       |
| comm     | decimal(7,2)             | YES  |     | NULL    |       |
| deptno   | int(2) unsigned zerofill | YES  |     | NULL    |       |
+----------+--------------------------+------+-----+---------+-------+
8 rows in set (0.00 sec)

mysql> desc salgrade;
+-------+---------+------+-----+---------+-------+
| Field | Type    | Null | Key | Default | Extra |
+-------+---------+------+-----+---------+-------+
| grade | int(11) | YES  |     | NULL    |       |
| losal | int(11) | YES  |     | NULL    |       |
| hisal | int(11) | YES  |     | NULL    |       |
+-------+---------+------+-----+---------+-------+
3 rows in set (0.00 sec)

一. 多表查询

多表查询,就是在由多张表组合而成的大表中,检索符合条件的数据。

语法:select ... from 表1,表2,... [where ...];

多张表进行组合,就是在对表进行笛卡尔积,图1.1为双表笛卡尔积运算的规则。由于实际项目中多张表之间可能会存在相互关联的字段,要对多表组合结果进行筛选去除非法组合,比如:对emp和dept表进行笛卡尔积组合运算时,emp表中的deptno字段和dept表中的deptno字段相同才有意义,因此要通过适当的where条件,将无效的组合去除。

图1.1 笛卡尔积运算

MySQL还支持表的自连接,所谓自连接,就是同一张表连接其自身,图1.2为自连接的示意图,可以理解为两张完全相同的表做笛卡尔积。

图1.2 表的自连接
  • 显示部门号为20的部门名、员工姓名以及员工编号

部门名在表dept中,员工姓名和员工编号在表emp中,emp中还存有员工所属的部门编号,因此需要将表emp和dept进行组合,并通过emp.deptno=dept.deptno排除不正确的组合项。

mysql> select empno,ename,emp.deptno from emp,dept where emp.deptno=dept.deptno and emp.deptno=20;
+--------+-------+--------+
| empno  | ename | deptno |
+--------+-------+--------+
| 007369 | SMITH |     20 |
| 007566 | JONES |     20 |
| 007788 | SCOTT |     20 |
| 007876 | ADAMS |     20 |
| 007902 | FORD  |     20 |
+--------+-------+--------+
5 rows in set (0.00 sec)
  • 显示每个员工的姓名、薪资和薪资级别 

员工姓名和薪资在表emp中,薪资等级信息在表salgrade中,需要将表emp和salgrade进行组合查询。在salgrade表中存有每种薪资等级的最高薪资hisal和最低薪资losal,筛选满足条件losal <= sal <= hisal的行即可。

mysql> select ename,sal,grade from emp,salgrade  -- 组合表
    -> where sal>=losal and sal<=hisal;          -- 筛选条件
+--------+---------+-------+
| ename  | sal     | grade |
+--------+---------+-------+
| SMITH  |  800.00 |     1 |
| ALLEN  | 1600.00 |     3 |
| WARD   | 1250.00 |     2 |
| JONES  | 2975.00 |     4 |
| MARTIN | 1250.00 |     2 |
| BLAKE  | 2850.00 |     4 |
| CLARK  | 2450.00 |     4 |
| SCOTT  | 3000.00 |     4 |
| KING   | 5000.00 |     5 |
| TURNER | 1500.00 |     3 |
| ADAMS  | 1100.00 |     1 |
| JAMES  |  950.00 |     1 |
| FORD   | 3000.00 |     4 |
| MILLER | 1300.00 |     2 |
+--------+---------+-------+
14 rows in set (0.00 sec)

二. 子查询

子查询,就是在where条件中,嵌入select语句来作为判断条件的一部分。

2.1 单行子查询

单行子查询,就是通过select筛选出来的条件为单行数据,通过where将特定字段的值与select结果进行比较,得到满足要求的结果。

语法:select ... from TableName where [... (select ...)];

  • 查询薪资比CLARK高的员工姓名与薪资

在where条件中通过select子查询获取CLARK的薪资,筛选出sal大于CLARK薪资的行即可。

mysql> select ename,sal from emp where sal > (select sal from emp where ename='CLARK');
+-------+---------+
| ename | sal     |
+-------+---------+
| JONES | 2975.00 |
| BLAKE | 2850.00 |
| SCOTT | 3000.00 |
| KING  | 5000.00 |
| FORD  | 3000.00 |
+-------+---------+
5 rows in set (0.00 sec)
  • 查询与SMITH属于同一部门的员工的工号、姓名和所属部门
mysql> select empno,ename,deptno from emp
    -> where deptno = (select deptno from emp where ename='SMITH');
+--------+-------+--------+
| empno  | ename | deptno |
+--------+-------+--------+
| 007369 | SMITH |     20 |
| 007566 | JONES |     20 |
| 007788 | SCOTT |     20 |
| 007876 | ADAMS |     20 |
| 007902 | FORD  |     20 |
+--------+-------+--------+
5 rows in set (0.00 sec

2.2 多行子查询

首先介绍in、all、any三个关键字:

  • in:语法为in(选项1, 选项2, ... ),如果字段与in中选项之一完全匹配,那么返回结果为真,如:job in('MANAGER', 'CLERK', 'SALESMAN')的含义是,如果job是MANAGER、CLERK或者SALESMAN其中之一,就返回真。
  • all:将特定关键字与all内的所有行进行比较,如果与所有行的比较都满足条件,那么返回真,否则返回假。如:sal!=all(30,40,50),sal不是30、40、50其中之一返回真,否则返回假。
  • any:将特定关键字与any内的所有行进行比较,如果与其中某一行的比较为真,那么就返回真,否则返回假。如:sal = any(1000,2000),表示sal是1000或2000返回真,否则返回假。

下面三个案例,分别使用in、all、any进行多行子查询。

案例1:查询与10号部门工作岗位相同的员工工号、姓名、部门和岗位,但不包含10号部门员工

通过 in关键字 + select 子查询,将每个员工的job与10号部门具有的岗位进行比较,同时排除10号部门员工即可。

mysql> select empno,ename,deptno,job from emp where job in(select job from emp where deptno=10) and deptno!=10;
+--------+-------+--------+---------+
| empno  | ename | deptno | job     |
+--------+-------+--------+---------+
| 007566 | JONES |     20 | MANAGER |
| 007698 | BLAKE |     30 | MANAGER |
| 007369 | SMITH |     20 | CLERK   |
| 007876 | ADAMS |     20 | CLERK   |
| 007900 | JAMES |     30 | CLERK   |
+--------+-------+--------+---------+
5 rows in set (0.00 sec)

案例2:查询比30号部门所有员工工资都高的员工姓名、部门和工资

mysql> select ename,deptno,sal from emp where sal > all(select sal from emp where deptno=30);
+-------+--------+---------+
| ename | deptno | sal     |
+-------+--------+---------+
| JONES |     20 | 2975.00 |
| SCOTT |     20 | 3000.00 |
| KING  |     10 | 5000.00 |
| FORD  |     20 | 3000.00 |
+-------+--------+---------+
4 rows in set (0.00 sec)

案例三:查询比30号部门任意员工工资高的员工姓名、部门号和薪资,不包括30号部门员工

mysql> select ename,deptno,sal from emp where sal > any(select sal from emp where deptno=30);
+--------+--------+---------+
| ename  | deptno | sal     |
+--------+--------+---------+
| ALLEN  |     30 | 1600.00 |
| WARD   |     30 | 1250.00 |
| JONES  |     20 | 2975.00 |
| MARTIN |     30 | 1250.00 |
| BLAKE  |     30 | 2850.00 |
| CLARK  |     10 | 2450.00 |
| SCOTT  |     20 | 3000.00 |
| KING   |     10 | 5000.00 |
| TURNER |     30 | 1500.00 |
| ADAMS  |     20 | 1100.00 |
| FORD   |     20 | 3000.00 |
| MILLER |     10 | 1300.00 |
+--------+--------+---------+
12 rows in set (0.00 sec)

2.3 多列子查询

多列子查询,就是多个字段与select后的值进行比较,将要进行比较的字段使用圆括号括起来,每个字段之间通过逗号隔开。

语法:

select ...  from Table where (field1, filed2, ...) 运算符 (select field1, filed2, ... from Table)

  • 查询与SMITH部门和岗位完全相同的员工的工号、姓名、岗位和部门
mysql> select empno,ename,deptno,job from emp
    -> where (job,deptno) = (select job,deptno from emp where ename='SMITH')
    -> and ename != 'SMITH';
+--------+-------+--------+-------+
| empno  | ename | deptno | job   |
+--------+-------+--------+-------+
| 007876 | ADAMS |     20 | CLERK |
+--------+-------+--------+-------+
1 row in set (0.00 sec)

2.4 在from语句中使用子查询

在from语句中可以使用select子查询,方式一般为将select后的结果作为一张表,并给一个临时的名称,这张表一般会和其他的表进行组合,在组合后的表中进行查询。通过案例来演示如何在from中使用子查询。

  • 获取高于自己部门平均工资的员工姓名、部门工资和平均工资

在表emp中通过group by对部门分组,结合avg(sal)计算每个部门的平均工资,通过select生成一张包含部门号和部门平均工资的临时表tmp,并将avg(sal)重命名为avg_sal,将tmp与emp表组合,通过tmp.deptno=emp.deptno去除错误的组合,通过sal>avg_sal筛选大于部门平均工资的员工。

mysql> select ename,emp.deptno,sal,avg_sal from emp,
    -> (select avg(sal) avg_sal,deptno from emp group by deptno) tmp
    -> where emp.deptno=tmp.deptno and sal>avg_sal;
+-------+--------+---------+-------------+
| ename | deptno | sal     | avg_sal     |
+-------+--------+---------+-------------+
| KING  |     10 | 5000.00 | 2916.666667 |
| JONES |     20 | 2975.00 | 2175.000000 |
| SCOTT |     20 | 3000.00 | 2175.000000 |
| FORD  |     20 | 3000.00 | 2175.000000 |
| ALLEN |     30 | 1600.00 | 1566.666667 |
| BLAKE |     30 | 2850.00 | 1566.666667 |
+-------+--------+---------+-------------+
6 rows in set (0.00 sec)
  • 获取每个部门工资最低的员工的姓名、部门和工资

创建一张包含部门号deptno和部门最低工资min(sal)的临时表tmp,将tmp和emp进行组合,筛选符合条件的数据。

mysql> select ename,emp.deptno,sal from emp,
    -> (select min(sal) minSal,deptno from emp group by deptno) tmp
    -> where sal=minSal and emp.deptno=tmp.deptno;
+--------+--------+---------+
| ename  | deptno | sal     |
+--------+--------+---------+
| SMITH  |     20 |  800.00 |
| JAMES  |     30 |  950.00 |
| MILLER |     10 | 1300.00 |
+--------+--------+---------+
3 rows in set (0.00 sec)
  • 显示每个部门的部门信息(部门号、部门名、地址)和人员数量

通过select筛选在emp中根据deptno分组统计人员数量,获取一张包括部门编号和部门人员数量的表tmp,将这张表tmp与表dept组合,筛选符合条件的数据即可。

mysql> select dept.deptno,dept.dname,dept.loc,tmp.countEmp from dept,
    -> (select deptno,count(*) countEmp from emp group by deptno) tmp
    -> where dept.deptno=tmp.deptno;
+--------+------------+----------+----------+
| deptno | dname      | loc      | countEmp |
+--------+------------+----------+----------+
|     10 | ACCOUNTING | NEW YORK |        3 |
|     20 | RESEARCH   | DALLAS   |        5 |
|     30 | SALES      | CHICAGO  |        6 |
+--------+------------+----------+----------+
3 rows in set (0.00 sec)

三. 合并查询

3.1 union

union用于合并多个select语句筛选出来的数据(行),合并后的结果会自动去重。

  • 筛选出职位是MANAGER或薪资大于2500的员工
mysql> select ename,job,sal from emp where job='MANAGER' union
    -> select ename,job,sal from emp where sal>2500;
+-------+-----------+---------+
| ename | job       | sal     |
+-------+-----------+---------+
| JONES | MANAGER   | 2975.00 |
| BLAKE | MANAGER   | 2850.00 |
| CLARK | MANAGER   | 2450.00 |
| SCOTT | ANALYST   | 3000.00 |
| KING  | PRESIDENT | 5000.00 |
| FORD  | ANALYST   | 3000.00 |
+-------+-----------+---------+
6 rows in set (0.00 sec)

3.2 union all

union all与union类似,可以用于合并两条select语句的执行结果,与union不同的是,union all合并后的结果不会自动去重。使用union all筛选职位是MANAGER或薪资大于2500的员工,可见执行结果明显没有去重。

mysql> select ename,job,sal from emp where job='MANAGER' union all
    -> select ename,job,sal from emp where sal>2500;
+-------+-----------+---------+
| ename | job       | sal     |
+-------+-----------+---------+
| JONES | MANAGER   | 2975.00 |
| BLAKE | MANAGER   | 2850.00 |
| CLARK | MANAGER   | 2450.00 |
| JONES | MANAGER   | 2975.00 |
| BLAKE | MANAGER   | 2850.00 |
| SCOTT | ANALYST   | 3000.00 |
| KING  | PRESIDENT | 5000.00 |
| FORD  | ANALYST   | 3000.00 |
+-------+-----------+---------+
8 rows in set (0.00 sec)

四. 总结

  • 多表查询,就是将多个通过笛卡尔积组合的表作为一整张表进行查询,多表查询需要一些条件限制去除非法的组合。
  • 子查询就是在查询条件语句中使用select语句充当条件的一部分,可以在where中使用select,也可以在from中使用select。
  • union和union all可以合并两条select的结果,union会自动去重,union all不会去重。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

git远程操作,推送【push】,拉取【pull】,忽略特殊文件,配置别名,标签管理

文章目录 前言&#xff1a;新建远程仓库克隆推送【push】拉取【pull】 配置git忽略特殊文件给命令配置别名 标签管理理解标签创建标签操作标签 前言&#xff1a; 大家如果没有看过前几章git的基础操作的话&#xff0c;推荐先看一下&#xff0c;看完再来看这个远程操作&#xf…

ARM12.26

整理三个按键中断代码 key_it.h #ifndef __KEY_IT_H__ #define __KEY_IT_H__ #include"stm32mp1xx_gpio.h" #include"stm32mp1xx_gic.h" #include"stm32mp1xx_exti.h" #include"stm32mp1xx_rcc.h" #include"led.h" void k…

ARCGIS PRO SDK 要素空间关系

一、要素与要素查询&#xff0c;返回的是bool值 1、 Touches 判断几何要素是否接触 Touches 如果 geometry1 与 geometry2 接触&#xff0c;则返回 true&#xff0c;否则 false。 touches GeometryEngine.Instance.Touches(Geometry1, Geometry2) 2、…

ROS 传感器 激光雷达

激光雷达&#xff0c;全称Light Detection And Ranging&#xff0c;主要用于利用激光来检测物体以及测量与物体之间的距离&#xff0c;是一种重要的传感器技术&#xff0c;这种技术被广泛应用于自动驾驶、无人船、无人机等领域&#xff0c;用于避障和环境探测。 在ROS环境中&a…

什么是阿里云负载均衡SLB?

目录 硬件或软件负载均衡的区别是什么&#xff1f; 什么是阿里云负载均衡SLB&#xff1f; 阿里云传统型负载均衡CLB 硬件或软件负载均衡的区别是什么&#xff1f; 通过专用硬件实现负载均衡&#xff0c;那么整体成本会较高&#xff0c;而且设备容易出现单点故障&#xff0c;…

简析SoBit 跨链桥图文教程

从BTC网络到Solana网络桥接BRC20 1.打开SoBit平台&#xff1a;在您的网络浏览器中启动SoBit Bridge应用程序。 2.连接您的钱包&#xff1a; 选择SoBit界面右上角的比特币网络来连接您的数字钱包。 3.选择源链、目标链和您想桥接的代币&#xff1a; 从下拉菜单中选择’BTC’作为…

弱电工程计算机网络系统基础知识

我们周围无时无刻不存在一张网&#xff0c;如电话网、电报网、电视网、计算机网络等&#xff1b;即使我们身体内部也存在许许多多的网络系统&#xff0c;如神经系统、消化系统等。最为典型的代表即计算机网络&#xff0c;它是计算机技术与通信技术两个领域的结合。 计算机网络的…

【PTA】L1-016 验证身份(C++)

题目链接 &#xff1a; 题目要求&#xff1a; 一个合法的身份证号码由17位地区、日期编号和顺序编号加1位校验码组成。校验码的计算规则如下&#xff1a; 首先对前17位数字加权求和&#xff0c;权重分配为&#xff1a;{7&#xff0c;9&#xff0c;10&#xff0c;5&#xff0…

axios进行图片上传组件封装

文章目录 前言图片上传接口&#xff08;axios通信)图片上传使用upload上传头像效果展示总结 前言 node项目使用 axios 库进行简单文件上传的模块封装。 图片上传接口&#xff08;axios通信) 新建upload.js文件&#xff0c;定义一个函数&#xff0c;该函数接受一个上传路径和一…

.Net7.0 或更高版本 System.Drawing.Common 上传图片跨平台方案

项目升级.Net7.0以后&#xff0c;System.Drawing.Common开关已经被删除&#xff0c;且System.Drawing.Common仅在 Windows 上支持 &#xff0c;于是想办法将原来上传图片验证文件名和获取图片扩展名方法替换一下&#xff0c;便开始搜索相关解决方案。 .Net6.0文档&#xff1a;…

【vue滚动条插件vuescroll】【vue自定义滚动条】

文章目录 前言一、使用步骤1.下载2.引入库三、在组件中如何使用&#xff1f;四、跳转到顶部的方法scrollTo() 五、效果总结 前言 由于浏览器自带的滚动条比较不符合设计图&#xff0c;所以在大部分项目中&#xff0c;我们都会自定义滚动条的样式&#xff0c;来还原设计图&…

Hive实战:词频统计

文章目录 一、实战概述二、提出任务三、完成任务&#xff08;一&#xff09;准备数据文件1、在虚拟机上创建文本文件2、将文本文件上传到HDFS指定目录 &#xff08;二&#xff09;实现步骤1、启动Hive Metastore服务2、启动Hive客户端3、基于HDFS文件创建外部表4、利用Hive SQL…

安装kafka

静态文件安装&#xff08;单机&#xff09; 解压到指定目录&#xff08;解压到 /usr&#xff09; tar -zxf kafka_2.11-2.2.0.tgz -C /usr/ 到指定的解压目录下 cd /usr/kafka_2.11-2.2.0/ 配置主机名 查看是否配置了HOSTNAME vim /etc/sysconfig/network 没有就新增 HOSTNA…

记录汇川:MODBUS TCP-梯形图

H5U的MODBUS通信不需要编写程序&#xff0c;通过组态MODBUS通信配置表&#xff0c;实现数据通信。 Modbus-TCP 主站即Modbus-TCP客户端&#xff0c;通过Modbus-TCP配置&#xff0c;可最多支持同时与31个 Modbus-TCP服务器&#xff08;从站&#xff09;进行通讯。 …

大数据与人工智能|全面数字化战略与企业数字化转型(第1节 )

要点一&#xff1a;培养跨学科思维 在分析时&#xff0c;需要采用多学科的思维方式 结果不重要&#xff0c;重要的是如何提炼现象、分析问题和得出结论的过程。 1. 介绍了锤子精神和多学科思维方式的重要性。指出了只从自身学科出发解决问题的局限性。 2. 提倡跨学科思维方式&a…

C语言易错知识点九(指针(part three))

❀❀❀ 文章由不准备秃的大伟原创 ❀❀❀ ♪♪♪ 若有转载&#xff0c;请联系博主哦~ ♪♪♪ ❤❤❤ 致力学好编程的宝藏博主&#xff0c;代码兴国&#xff01;❤❤❤ 许久不见&#xff0c;甚是想念&#xff0c;本大忙人已经很久没有更新博客了&#xff0c;我想大概我的粉丝们早…

数据库原理及应用·关系数据库标准语言SQL

4.1 SQL概述 4.1.1 SQL的产生和发展 1.产生 1974年&#xff0c;SQL语言的雏形最早由美国IBM公司的Raymond F. Boyce和Donald D. Chamberlin提出 1975-1979年&#xff0c;在System R上首次实现&#xff0c;由IBM的San Jose研究室研制&#xff0c;称为SEQUEL 2.发展 1986年推…

文件夹共享功能的配置 以及Windows server2012防火墙的配置

目录 一. 配置文件夹共享功能 1.1 为什么需要配置文件夹共享功能 1.2 配置文件夹共享 1.3 访问共享文件夹 1.4 配置取消 用户名和密码认证 二. windows server 2012防火墙配置 思维导图 一. 配置文件夹共享功能 1.1 为什么需要配置文件夹共享功能 我们在工作和生活中经…

RM3100 stm32驱动(硬件i2c)

目录 RM3100接线HAL库I2C函数HAL_I2C_Mem_ReadHAL_I2C_Mem_WriteHAL_I2C_Master_Transmit / HAL_I2C_Master_Receive例子 HSHAKE寄存器 cubemx配置RM3100寄存器驱动最终效果 RM3100接线 原理图 SA0 SA1接地&#xff0c;此时i2c设备地址为0100000&#xff0c;即0x20 如果SA0接…

Scikit-Learn线性回归(一)

Scikit-Learn线性回归一 1、线性回归概述1.1、回归1.2、线性1.3、线性回归1.4、线性回归的优缺点1.5、线性回归与逻辑回归2、线性回归的原理2.1、线性回归的定义与原理2.2、线性回归的损失函数3、Scikit-Learn线性回归3.1、Scikit-Learn库3.2、Scikit-Learn线性回归API3.3、Sci…
最新文章