Mysql表的复合查询

1.基本查询

使用scott案列

----来源csdn:

Mysql下-scott用户表的创建_风泊月mysql 员工表-CSDN博客

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

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

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

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

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

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

order by deptno asc,sal desc;

不显示其他信息:

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

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

按年薪排:

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

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

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

显示一个最高:

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

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

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

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

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

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

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

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

通过format进行格式化

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

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

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

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

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

案例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;

2.多表查询

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

同样引用

Mysql下-scott用户表的创建_风泊月mysql 员工表-CSDN博客

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

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

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

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

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

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

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

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

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

只显示有意义的数据:

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

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

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

3.自连接

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

如:

dept表:

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

select * from dept as t1,dept as t2;

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

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

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

select enam from emp where empno=7839;

就找到了CLARK的领导姓名

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

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

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

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

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

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

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

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

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

4.子查询

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

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

4.1单行子查询

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

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

4.2多行子查询

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

select distinct sal from emp where demptno=30;

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

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

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

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

4.3多列子查询

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

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

先拿到ALLEN的部门和岗位:

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

包含两列信息

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

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

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

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

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

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

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

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

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

select avg(sal) from emp group by deptno;

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

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

再将工资进行比较

最后将打印信息进行筛选

再将上表交给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;

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

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

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

再除去工资不匹配的

再比对部门是否一致

最后除去无用信息

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

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

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

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

得到结果

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

6.合并查询

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

6.1union

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

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

先找工资大于2500的员工

再找职位为MANAGER的员工

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

6.2union all

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

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

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

相关推荐
大飞哥~BigFei36 分钟前
乐企数电发票分布式发票号码生成重复的问题修复思路分享
java·分布式·数电发票号码生成
qq_4476630536 分钟前
手写SpringMVC(基本框架)
java·开发语言
noravinsc2 小时前
django admin AttributeError: ‘UserResorce‘ object has no attribute ‘ID‘
数据库·django·sqlite
王有品4 小时前
Spring MVC 多个拦截器的执行顺序
数据库·spring·mvc
极小狐5 小时前
如何使用极狐GitLab 的外部状态检查功能?
数据库·ci/cd·gitlab·devops·mcp
Leo.yuan5 小时前
数据仓库建设全解析!
大数据·数据库·数据仓库·数据分析·spark
闪电麦坤955 小时前
SQL:子查询(subqueries)
数据库·sql
活跃的煤矿打工人5 小时前
【星海出品】分布式存储数据库etcd
数据库·分布式·etcd
文牧之5 小时前
PostgreSQL的扩展 pgcrypto
运维·数据库·postgresql
_一条咸鱼_6 小时前
揭秘 Android TextInputLayout:从源码深度剖析其使用原理
android·java·面试