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

相关推荐
丫头,冲鸭!!!7 分钟前
记账网站3-连数据库
数据库·个人开发
灯澜忆梦25 分钟前
【MySQL12】进阶篇 | SQL优化
数据库·sql·mysql·性能优化
IvorySQL32 分钟前
PostgreSQL 日报|PG18.5 回归测试崩溃问题(8 月 12 日)
大数据·数据库·人工智能·postgresql
ltl41 分钟前
学习型查询优化器:Neo、Bao、Balsa 与 LLM-CBO
数据库
ltl1 小时前
持久内存退场之后:ZNS SSD 与下一代非易失内存
数据库
故乡dee云3 小时前
AWS 产品太多不会选?按“网站、数据库、文件、日志”4 类需求快速匹配
数据库·云计算·aws
曹牧5 小时前
C#:问号
前端·数据库·c#
奇树谦5 小时前
《现代 Key-Value 数据库原理:从 B+Tree 到 LSM Tree》-第五篇:现代数据库横向对比
数据库·lsm-tree
李白客5 小时前
分布式集群与数据库产业:从单机到集群的架构跃迁与市场重构
数据库·分布式·架构
福大大架构师每日一题6 小时前
Redis 8.10.0 正式发布:紧凑哈希、批量导入、备份恢复、流与时序能力全面升级
数据库·redis·哈希算法