Mysql中的子查询

子查询

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

条件:
一条sql语句的查询结果作为另一条查询语句的条件或者查询结果。

嵌套:
多条sql语句嵌套使用,内部的sql查询语句称为子查询。

使用子查询解决的问题:不能够一步求解的问题。

示例:查询工资比SCOTT高的员工信息
1.select sal from emp where name = ‘SCOTT’;

查询出来SCOTT的工资是3000

2.select * from emp where sal>3000;

使用子查询解决上面的问题:

select * from emp where sal > (select sal from emp where name = ‘SCOTT’);

子查询注意的10个问题

  • 子查询语法中的小括号
  • 子查询的书写风格
  • 可以使用子查询的位置:where,select,having,from
  • 不可以使用子查询的位置:group by
  • == from后面的子查询==
  • 主查询和子查询可以不是同一张表
  • 一般不在子查询中使用排序;但在Top-N分析问题中,必须对子查询进行排序
  • 一般先执行子查询,再执行主查询;相关子查询例外
  • 单行子查询只能使用单行操作符;多行子查询只能使用多行操作符
  • 子查询中null值问题

在select后面使用子查询:

子查询必须是单行子查询(返回一行记录的子查询)

select empno ,ename,(select job from emp where empno =7839 ) 第四列 from emp;

在having 后面使用子查询:

select deptno,avg(sal) 
from emp
group by deptno
having avg(sal) > (select max(sal)
					from emp 
					where deptno = 30);

在from后面使用子查询:

# 查询员工信息:员工号,姓名,月薪
select *
from (select empno ,ename,sal from emp);#可以把from后面的子查询的结果看成是一张新的表(虚拟表)
#查询员工信息:员工号,姓名,月薪,年薪
select *
from (select empno ,ename,sal,sal*12 annsal from emp);

主查询和子查询可以不是同一张表

#查询部门名称是SALES的员工信息
select * 
from emp 
where deptno = (select deptno 
				from dept
				where dname = 'SALES' );
#主查询查询的是员工表,子查询查询的是部门表

#使用多表查询语句解决上面的问题
select e.*
from  emp e,dept d
where e.deptno = d.deptno and d.dname = 'SALES';

一般不在子查询中使用排序;但在Top-N分析问题中,必须对子查询进行排序

Top-N问题:

按照某个规律排序后,取出最前面的几条记录。

#找到员工表中工资最高的前三名
select rownum,empno,ename ,sal
from(slecet *
	 from emp
	 order by sal desc)
where rownum<=3;

一般先执行子查询,再执行主查询;相关子查询例外

#相关子查询
#找到员工表中薪水大于本部门平均薪水的员工
select empno,ename,sal,(select avg(sal) from emp where deptno = e.deptno) avgsal
from emp e
where sal>(select avg(sal) from emp where deptno = e.deptno);

单行子查询只能使用单行操作符;多行子查询只能使用多行操作符

单行子查询:子查询只返回一条记录;
单行操作符:
在这里插入图片描述

单行子查询只能使用单行操作符
一个主查询中可以有多个单行子查询

#查询员工信息,要求:职位与7566员工一样,薪水大于7782员工的薪水
select * from emp 
where job = (select job from emp where empno =7566)  and sal > (select sal fron where empno =7782);

#查询工资最低的员工信息
select * 
from emp
where sal = (select min(sal) from emp );

#查询最低工资大于20号部门最低工资的部门号和部门的最低工资
select deptno,min(sal)
from emp
group by deptno
having min(sal) > (select min(sal) from emp  where deptno = 20);

多行子查询:自查询返回的记录是多行的。

多行操作符:
在这里插入图片描述
in的使用:

#查询部门名称是SALES和ACCOUNTING的员工信息
select *
from emp
where deptno in (select deptno from dept where dname = 'SALES'or dname ='ACCOUNTING')
#使用多表查询语句完成
select e.*
from emp e,dept d
where e.deptno = d.deptno and 
(d.dname ='SALES'or d.dname ='ACCOUNTING');

any的使用:

#查询工资比30号部门任意一个员工高的员工信息
select * from emp 
where sal > any(select sal from emp where deptno = 30);
#大于集合的任意一个值,只需要大于集合中元素的最小值
select * from emp 
where sal > (select min(sal) from emp where deptno = 30)

all的使用

#查询工资比30号部门所有员工高的员工信息
select *
from emp 
where sal > all(select sal from emp where deptno = 30);
#大于集合的所有值,只需要大于集合的最大值
select * from emp 
where sal > (select max(sal) from emp where deptno = 30);

子查询中null值问题

单行子查询:

  • 如果子查询中的结果为null,那么主查询中的where条件永远为假,不会得到任何的结果。

多行子查询中的null值问题

#查询不是老板的员工
select * from emp 
where empno not in (select mqr from emp where mqr is not null);

in 和 exists 区别

#查询语文或者英语课程的成绩信息
select * from score where course_id in(select if from course where name ='语文'or name = '英语');

slect * from score  sco from (select sco.id from course cou where(name = '语文'or name = '英语') and cou.id = sco.course_id);

mysql中的in语句是把外表和内表作hash 连接,
而exists语句是对外表作loop循环,每次loop循环再对内表进行查询。一直大家都认为exists比in语句的效率要高,这种说法其实是不准确的。这个是要区分环境的。

  • 如果查询的两个表大小相当,那么用in和exists差别不大。
  • 如果两个表中一个较小,一个是大表,则子查询表大的用exists,子查询表小的用in。
  • not in 和not exists:如果查询语句使用了not in,那么内外表都进行全表扫描,没有用到索引; 而not extsts的子查询依然能用到表上的索引。所以无论那个表大,用not exists都比not in要快。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值