【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)右外连接

相关推荐
ss2732 小时前
食谱推荐系统功能测试如何写?
java·数据库·spring boot·功能测试
l1t2 小时前
DeepSeek总结的数据库外部表
数据库
m0_674294642 小时前
如何编写SQL存储过程性能对比_记录执行时间评估优化效果
jvm·数据库·python
014-code3 小时前
CompletableFuture 实战模板(超时、组合、异常链处理)
java·数据库
运气好好的3 小时前
怎样开启phpMyAdmin的操作审计日志_记录每条执行的SQL
jvm·数据库·python
それども3 小时前
DELETE 和 TRUNCATE TABLE区别
java·数据库·mysql
wenha3 小时前
数据库隔离级别
数据库·mysql·sqlserver·隔离级别
2401_871492854 小时前
Layui如何修改Layui默认的UI主题颜色(换肤功能实现)
jvm·数据库·python
Edward111111114 小时前
4.27mysql ,数据库,数据源
数据库·mysql
小徐敲java4 小时前
踩坑实录:MySQL8.0 导入SQL报错 2006 - MySQL server has gone away 完美解决
数据库·sql