目录

Mysql表的复合查询

Mysql表的复合查询

1.基本查询

使用scott案列

—-来源csdn:

https://i-blog.csdnimg.cn/direct/560ac0ea25ff4ab5bee419590d99e0fb.png

案列1:查询工资高于500或岗位为MANAGER的雇员,同时还要满足他们的姓名首字母为大小的J

查询雇员,从emp表中查询,sal>500 or job==’MANAGER’表示查询工资高于500或岗位为MANAGER, ename like ‘J%’表示查询ename为J开头。

https://i-blog.csdnimg.cn/direct/25cb7e75e7604cb6af908d0c984bf169.png

也可以使用函数进行截取ename来进行判断:

substring(ename,1,1)=’J’;

https://i-blog.csdnimg.cn/direct/6849b3d0a99244a593615142ac999a0d.png

案例2:将雇员按部门号升序而工资降序进行排序:

—-表示将相同部门号的雇员按工资,以降序排列

order by deptno asc,sal desc;

https://i-blog.csdnimg.cn/direct/88efa3241aae441f913e30bdcce081c0.png

不显示其他信息:

https://i-blog.csdnimg.cn/direct/e0c04f44e7e349fe9dcfb0e52daf26c9.png

案例3:按年薪降序进行排序

年薪等于sal*12+comm comm为奖金

按年薪排:

https://i-blog.csdnimg.cn/direct/4127b85918264844ac3b3a13c4d601d3.png

加上奖金(comm可为null,当comm为null时,不能参加运算)

ifnull(comm,0)表示comm若为null就取0,若不为null就取comm

https://i-blog.csdnimg.cn/direct/3daeaaa7aafc40039d2ddc067607a1ea.png

案例4:显示工资最高的员工的名字和工作岗位:

显示一个最高:

https://i-blog.csdnimg.cn/direct/87a98794cd6846b196ca6ffa756a51e9.png

但是可能有多个员工工资都为最高工资:

通过子查询和聚合函数进行查找

先通过子查询select max(sal) from emp找到最高工资,再交给where进行筛选:

select ename,job from emp where sal=(select max(sal) from emp);

https://i-blog.csdnimg.cn/direct/dbb7867ab4ef48eda60f054660bcaef6.png

案例4:显示工资高于平均工资的员工名和工资

同样通过select子句找出平均工资,再交给where进行筛选:

select ename,sal from emp where sal>(select avg(sal) from emp);

https://i-blog.csdnimg.cn/direct/cc4edc34b63a457c82acd800fe0b06e4.png

案例5:显示每个部门的平均工资和最高工资,只显示整数部分

通过format进行格式化

通过将每个部门分组(group by)再寻找平均工资和最高工资

https://i-blog.csdnimg.cn/direct/227e0e90185c49228603481bf91266a9.png

案例6:显示平均工资低于2000的部门号和它的平均工资:

先算每个部门的平均工资:

https://i-blog.csdnimg.cn/direct/ce05afbc2bd84aa3a478f75d94bcbeb3.png

再通过having对聚合函数处理的数据进行筛选:

select deptno avg(sal) 平均工资 from emp group by deptno having 平均工资>2000;

https://i-blog.csdnimg.cn/direct/08070c46b8734bf4b9b4b53279409cb7.png

案例7:显示每种岗位的雇员总数,平均工资

先算每种岗位的员工总数:

select  count(*) from emp group by job;

再算平均工资:

select count(*),avg(sal) from emp group by job;

再优化显示:

select job 岗位,count(*) 岗位员工总数,format(avg(sal),0) 岗位平均工资 from emp group by job;

https://i-blog.csdnimg.cn/direct/82654a4066204f038968e6b250ccf085.png

2.多表查询

实际开发中数据往往来自不同的表,所以需要多表查询。

同样引用

来源的soctt数据库进行演示:

案例1:显示雇员名,工资和部门名

其中的部门名不属于员工表,而是部门表,需要从两张表进行整合:

先拿到两张表的全部数据:select * from emp,dept;

https://i-blog.csdnimg.cn/direct/7e90cd76c3be46438c880048ea076371.png

发现是将emp表中的一个数据与dept表中的所有数据进行穷举:

https://i-blog.csdnimg.cn/direct/bbfd0d5442cb4644ab2fbc8091651a1f.png

https://i-blog.csdnimg.cn/direct/6e78330c6bbb43bfa32665ff92f9092c.png

每一个emp表中的数据都会与dept表中的所有数据进行组合。

——称为两张表中的笛卡尔积,将两张表中的所有数据都进行了组合。

但是一个emp表中的数据只有一个dept表中的数据对它有意义,所以要将对它没用的数据筛选出去:

select * from emp,dept where emp.deptno=dept.deptno;

只显示有意义的数据:

https://i-blog.csdnimg.cn/direct/1c6de99efd6046e18167e9acc6966fe7.png

再筛选出要求打印的员工名,工资,部门名:

select ename,sel,dname from emp,dept where emp.deptno=dept.deptno;

https://i-blog.csdnimg.cn/direct/9b763ced66914943a02afc9b27c2cbb4.png

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

https://i-blog.csdnimg.cn/direct/79116f2fa74e430f8fca663f429bdc17.png

3.自连接

自连接时指在同一张表连接查询—–对一张表中的数据做笛卡尔积

如:

dept表:

https://i-blog.csdnimg.cn/direct/e20605c639a84f1a825d149fc0a3dcc0.png

将同一张表中的数据进行笛卡尔积,因为表名不能重复出现,所以用as进行重命名:

select * from dept as t1,dept as t2;

https://i-blog.csdnimg.cn/direct/2617001bd3f94f12bf18289fe75bf5ac.png

https://i-blog.csdnimg.cn/direct/05e0b68cdc244731a7f4500615f5e22c.png

案例1:显示员工CLARK的上级领导的编号和姓名—mgr是上级编号,同时也是上级的empno

先在员工表中找CLARK的领导的编号:select mgr from emp where ename=’CLARK’;

https://i-blog.csdnimg.cn/direct/b2b4ef0608f648ff9feb8ef3f6949ab7.png

再在员工表中找编号为7839的员工姓名:

select enam from emp where empno=7839;

https://i-blog.csdnimg.cn/direct/154abd13adb64573bfc8be1c9c50435f.png

就找到了CLARK的领导姓名

通过子查询来一条sql实现:

select ename,empno where empno=(select mgr from emp where ename=’CLARK’);

https://i-blog.csdnimg.cn/direct/6826eb05f786485ea2cd54bd30f5c79f.png

或通过自连接实现一条sql语句实现:

先做笛卡尔积,再筛选出员工CLARK与同一张表中所有员工组合的数据:

select * from emp e1,emp e2 where e1.ename=’CLARK’;

https://i-blog.csdnimg.cn/direct/2eac438cf19c4b27909cee9d45a49c60.png

再筛选出与e1表中的CLARK的mgr编号对应的empno编号

select * from emp e1,emp e2 where e1.ename=’CLARK’ and e1.mgr=e2.empno;

https://i-blog.csdnimg.cn/direct/d7346ec5312f4827ade9bef948ce7c47.png

再优化,仅打印领导编号和姓名:

select e2.empno,e2.ename from emp e1,emp e2 where e1.ename=’CLARK’ and e1.mgr=e2.empno;

https://i-blog.csdnimg.cn/direct/75bf4f22e7544e4da7e5cf63514be15c.png

4.子查询

子查询是指嵌入在其他sql语句中的select语句,也叫嵌套查询

select 和子查询后的表结构都能进行笛卡尔积

4.1单行子查询

返回一行记录的子查询—子查询返回的结果是单列单行的

案例:显示和KING同一部门的员工

https://i-blog.csdnimg.cn/direct/de8116ab6eac4b5fa0b2fba5a71cc0cd.png

4.2多行子查询

返回多行记录的子查询—-子查询返回的结果是多行单列的

4.2.1  in关键字使用,in是用来判断列值是否在某一个集合当中。

此处用于筛选是否在多行子查询返回的集合当中。

案例:查询和10号部门的员工的工作岗位相同的雇员的名字,岗位,工资,部门号,但是不包括10号部门本身的员工。

先找出10号部门员工去重后的工作岗位:

https://i-blog.csdnimg.cn/direct/b8e88bec93e94941baa32e13a86f4802.png

再找出与这些工作岗位相同的员工的名字,岗位,工资,部门号:

用in判断是否在子查询集合当中

https://i-blog.csdnimg.cn/direct/fa169763c91f47358047a3e69839c16f.png

再去除10号部门的员工本身。

用deptno <> 10 来表示deptno不等于10

https://i-blog.csdnimg.cn/direct/fed22c8b1d00403488c46caeb7dd4e1c.png

4.2.2 all关键字—-与子查询返回的所有行进行比较

any关键字—与子查询返回的任意一行进行比较,只要有一个为真,就为真

案例:显示工资比部门号为30号的所有员工的工资都高的员工的姓名,工资和部门号

先拿到30号部门的员工最高工资:

select max(sal) from emp where deptno=30;

https://i-blog.csdnimg.cn/direct/27c130ebafd248459af3174a0317fabf.png

再筛选工资高于30部门最高工资的员工的姓名,工资和部门号:

select ename ,sal,deptno from emp where sal>(select max(sal) from emp where deptno=30);

https://i-blog.csdnimg.cn/direct/f4c468127d7243c5a920596d3a72ef5c.png

也可以通过多行子查询进行筛选:

先拿到30号部门所有人的工资:

select distinct sal from emp where demptno=30;

https://i-blog.csdnimg.cn/direct/9e15d1a3f2564b078ccffd272dd958cf.png

再找出比30号部门所有人工资都高的员工—通过all将数据与子查询返回的所有数据进行比较。

select ename,sal,deptno from emp where sal > all(select distinct sal from emp where deptno=30);

https://i-blog.csdnimg.cn/direct/1135d51ef26e4e37b3fdb7da3b83932a.png

通过any语句找出比30号部门任意一员工工资高的员工,30号部门员工除外:

select ename,sal,deptno from emp where sal> any(select distinct sal from emp where deptno=30) and deptno <> 30;

https://i-blog.csdnimg.cn/direct/0fe9f34dc6794af8ab17f1b2226574a9.png

4.3多列子查询

单行子查询是指子查询指返回单列,单行数据;多行子查询是指返回单列多行数据,都是针对单列而言的,而多列子查询是指查询多个列数据的子查询语句。

案列:查询和ALLEN员工的部门和岗位完全相同的员工,不包含ALLEN自身

先拿到ALLEN的部门和岗位:

select deptno,job from emp where ename=’ALLEN’;

https://i-blog.csdnimg.cn/direct/ce60d57fd6124609a4164fbef7ccb027.png

包含两列信息

再查找与这两列信息都相同的员工

select * from emp where (deptno,job)=(select deptno,job from emp where ename=’ALLEN’);

https://i-blog.csdnimg.cn/direct/cc07dec68a8041949ff64e2fc11d574a.png

再去除ALLEN自身:and ename <>’ALLEN’;

https://i-blog.csdnimg.cn/direct/46ba34aa70084bbca48bfbe0271d24a6.png

也可以通过in,all,any进行多列多行子查询。

目前全部的子查询,都是在where字句中充当判断条件,但是查询出来的临时表结构,在本质是也是表。

5.在from字句中使用子查询

子查询语句出现在from子句中—-将一个子查询返回的数据作为一个临时表使用。

案列1:显示每个高于自己部门平均工资的员工姓名,部门,工资,平均工资,最后拿到每个人的办公地点

先拿到每个部门的平均工资:

select avg(sal) from emp group by deptno;

https://i-blog.csdnimg.cn/direct/c9f0a02b9da347ef9d88df6d56b6c836.png

再将部门平均工资表和员工表做笛卡尔积,

https://i-blog.csdnimg.cn/direct/62cf9cbe2ea34deea04d099fd18abfaa.png

拿到员工部门号和平均工资部门号相同的,

https://i-blog.csdnimg.cn/direct/c2a74e5230f44e00bd15002099d06996.png

再将工资进行比较

https://i-blog.csdnimg.cn/direct/0dfa76c22f7f43d98b8a4eb970bd0ff5.png

最后将打印信息进行筛选

https://i-blog.csdnimg.cn/direct/7c3eceef55394d799eac126022c20453.png

再将上表交给from拿到这些人的办公地点

select t1.ename,dept.loc,t1.deptno from dept,(select  emp.ename,emp.deptno from emp,(select deptno,avg(sal) 部门平均工资 from emp group by deptno) tmp where  emp.deptno=tmp.deptno and emp.sal>tmp.部门平均工资)  t1 where  t1.deptno=dept.deptno;

https://i-blog.csdnimg.cn/direct/a27a63fe42b94123b0ff82d008886243.png

案列2:查找每个部门工资最高的人的姓名,工资,部门,最高工资

先拿到每个部门工资最高的人

https://i-blog.csdnimg.cn/direct/dee5d17b0ea64d6ebb17ee8d4e6f8894.png

再将这张表交给from与emp表进行笛卡尔积

https://i-blog.csdnimg.cn/direct/45930de40d6b4f86a338781939c3145c.png

再除去工资不匹配的

https://i-blog.csdnimg.cn/direct/3cc7c07b7bba4244b5279df6c2c60f5c.png

再比对部门是否一致

https://i-blog.csdnimg.cn/direct/e6fb9f7844a0432b97478bd5daaea755.png

最后除去无用信息

https://i-blog.csdnimg.cn/direct/882a5628afe945dfafdca1617d958792.png

案例3:显示每个部门的部门名,编号,地址和人员数量

先拿到每个部门的人员数量

https://i-blog.csdnimg.cn/direct/8763b0c63d8042d2ad6f65836268f580.png

再将上表交给from与dept表进行笛卡尔积

https://i-blog.csdnimg.cn/direct/8f4df81db4b74bc5bcf0ef4434c1deb4.png

再筛选出两边部门号一致的数据

https://i-blog.csdnimg.cn/direct/a062c94ade55486982125e9fe93de138.png

得到结果

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

6.合并查询

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

6.1union

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

案例:将工资大于2500或职位时MANAGER的人展示

先找工资大于2500的员工

https://i-blog.csdnimg.cn/direct/389ac5d945d64c059848a6abdfeccac7.png

再找职位为MANAGER的员工

https://i-blog.csdnimg.cn/direct/1b197d54ee55488ea9d962832fa6337b.png

最后取得两个结果集的并集

https://i-blog.csdnimg.cn/direct/c103f749f87147f3ac26c1c75dbca467.png

6.2union all

取两结果的并集,不对结果中的重复行去除。

案例:同样将工资大于2500或职位为MANAGER的人展示

select * from emp where sal>2500 union all select * from emp where job=’MANAGER’;

https://i-blog.csdnimg.cn/direct/909ce355f9264ef98ac60a4e627dc368.png