【MySQL】解锁表的 N 种牵手方式:SQL 连接与子查询漫游(复合查询)

一、多表查询

显示雇员名、雇员工资以及所在部门的名字:

为了得出结果,我们必须让这两张表合并成一张表:

得到的一张非常大的表,这个表是由 emp 表的第一行和 dept 表的第一行、第二行等进行组合而来,以此类推,emp 表的第二行和 dept 的表的第一行、第二行等进行组合等等,最终得到这张表;这个结果称为笛卡尔积;

为了让员工的 emp 的部门编号和 dept 的部门编号进行适配,最终达成部门一致:

最后:显示员工名字、工资、部门:

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

显示各个员工的姓名,工资,及工资级别:

二、自连接

对同一张表进行笛卡尔积的操作称为自连接:

显示员工FORD的上级领导的编号和姓名(mgr是员工领导的编号--empno):

1)使用子查询:

2)自连接:

三、单行子查询

显示SMITH同一部门的员工:

三、多行子查询

查询和10号部门的工作岗位相同的雇员的名字,岗位,工资,部门号,但是不包含10自己:

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

显示工资比部门30的任意员工的工资高的员工的姓名、工资和部门号(包含自己部门的员工):

四、多列子查询

查询和SMITH的部门和岗位完全相同的所有雇员,不含SMITH本人:

mysql> select * from emp where (deptno,job) = (select deptno,job from emp where ename='SMITH');

+--------+-------+-------+------+---------------------+---------+------+--------+

| empno | ename | job | mgr | hiredate | sal | comm | deptno |

+--------+-------+-------+------+---------------------+---------+------+--------+

| 007369 | SMITH | CLERK | 7902 | 1980-12-17 00:00:00 | 800.00 | NULL | 20 |

| 007876 | ADAMS | CLERK | 7788 | 1987-05-23 00:00:00 | 1100.00 | NULL | 20 |

+--------+-------+-------+------+---------------------+---------+------+--------+

2 rows in set (0.00 sec)

mysql> select * from emp where (deptno,job) = (select deptno,job from emp where ename='SMITH') and ename != 'SMITH';

+--------+-------+-------+------+---------------------+---------+------+--------+

| empno | ename | job | mgr | hiredate | sal | comm | deptno |

+--------+-------+-------+------+---------------------+---------+------+--------+

| 007876 | ADAMS | CLERK | 7788 | 1987-05-23 00:00:00 | 1100.00 | NULL | 20 |

+--------+-------+-------+------+---------------------+---------+------+--------+

1 row in set (0.00 sec)

mysql> select * from emp where (deptno,job) in (select deptno,job from emp where ename='SMITH') and ename != 'SMITH';

+--------+-------+-------+------+---------------------+---------+------+--------+

| empno | ename | job | mgr | hiredate | sal | comm | deptno |

+--------+-------+-------+------+---------------------+---------+------+--------+

| 007876 | ADAMS | CLERK | 7788 | 1987-05-23 00:00:00 | 1100.00 | NULL | 20 |

+--------+-------+-------+------+---------------------+---------+------+--------+

1 row in set (0.01 sec)

五、在 from 子句中使用子查询

之前我们都是在 where 右侧使用子查询,现在我们来使用在 from 中使用子查询:

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

mysql> select * from emp,(select deptno,avg(sal) myavg from emp group by deptno) tmp where emp.deptno=tmp.deptno and emp.sal>tmp.myavg;

·查找每个部门工资最高的人的姓名、工资、部门、最高工资:

mysql> select ename,sal,t1.deptno,mymax from emp t1,(select deptno,max(sal) mymax from emp group by deptno) t2 where t1.deptno=t2.deptno and t1.sal=t2.mymax;

显示每个部门的信息(部门名,编号,地址)和人员数量:

mysql> select t1.dname,t1.loc,t2.dept_num,t1.deptno from dept t1,(select deptno,count(*) dept_num from emp group by deptno) t2 where t1.deptno=t2.deptno;

解决多表问题的本质:想办法将多表转换成单表,所以在 MySQL 中,所有的 select 的问题全部都可以转成单表问题;

六、合并查询

在实际应用中,为了合并多个select的执行结果,可以使用集合操作符union,union all;

union:该操作符用于取得两个结果集的并集。当使用该操作符时,会自动去掉结果集中的重复行。

将工资大于2500或职位是MANAGER的人找出来:

union all:该操作符用于取得两个结果集的并集。当使用该操作符时,不会去掉结果集中的重复行。

七、内连接

八、外连接

1)左外连接

查询所有学生的成绩,如果这个学生没有成绩,也要将学生的个人信息显示出来:

2)右外连接

相关推荐
工业涂料百问5 小时前
【环保合规】系列(四)工业涂料碳足迹怎么算?边界定义、因子选择与减排优先级拆解
数据库
wuyk5556 小时前
【Socket 进阶之路】第 7 章 IO 多路复用 select & poll 完整实战|多 fd 监听、超时等待、优缺点横向对比
服务器·开发语言·网络·数据库·物联网
文人sec6 小时前
grant 之后要跟着 flush privileges 吗?要不要使用分区表?
数据库·mysql·adb·数据分析
高级程序源6 小时前
django招聘网站信息爬取与分析系统79704-计算机课程设计、毕业设计
后端·python·mysql·小程序·django·flask·课程设计
Omics Pro6 小时前
上海AI Lab孙思琦×高张阳:虚拟细胞代码库智能体
数据库·人工智能·算法·机器学习·自然语言处理
旺仔不是程序员6 小时前
相关子查询与性能优化:PostgreSQL 逐行执行的代价与 JOIN 重写
数据库·后端·sql
YangYang9YangYan7 小时前
2026 电商数据运营校招 JD 梳理|岗位任务、技能与面试考点汇总
大数据·数据库·数据分析
Sun 32857 小时前
读懂集中式主备的集群状态与节点角色
数据库·opengauss·集群·节点角色·磐维数据库·运行状态
毕业设计7037 小时前
(免费领源码) SpringBoot 游戏交易平台17600-java、PHP、python、C#、小程序、大数据、单片机、网络工程等)
java·spring boot·mysql·决策树·mybatis·idea·推荐算法
溪语流沙7 小时前
Django + Vue电商项目第001讲:开篇|注册登录加增删改查,那不是电商
redis·python·mysql·docker·typescript·django·vue