回顾:
1、sql的执行顺序
select ⑤
from ①
where ②
group by ③
having ④
order by ⑥
2、关联查询
多表联合查询,杜绝笛卡尔积现象。
要求N张表联合,必须至少有N-1个连接条件。
内连接:查询出所有满足连接条件的数据。
外连接:查询出数据,满足+不满足条件的数据
左外连接
左表驱动表(所有数据)+ 右表匹配表(匹配)
右外连接
左表匹配表(匹配)+ 右表驱动表(所有数据)
全外连接
左表驱动表(所有数据)+ 右表驱动表(所有数据)
自连接
特殊连接查询
驱动、匹配表都来自于同一张表。
正课:
1、子查询
你是sql大牛,能否写一条select sql就能查询出想要的数据。
如:查询30部门最大工资的员工信息。
--错
select *,max(sal) from emp
where deptno = 30;
select * from emp where deptno = 30
and sal = (
--30部门最高工资
select max(sal) from emp
where deptno = 30
);
如上所述:
当无法使用一条select sql完成一个功能时,
可以考虑使用sql嵌套的方式来完成。
sql嵌套:
一条SQL语句中嵌套着另一条SQL查询语句。
又被称为---子查询。
被嵌套在SQL语句中的查询SQL,称为子查询,
子查询所在的那条SQL语句,称为父查询。
注意:子查询可以使用在DDL、DML、DQL中,
通常一般使用在DQL中为多。
1)、子查询使用在DDL中
create table emp_copy
as (select empno,ename,job,sal,deptno
from emp
);
结论:子查询使用在建表语句中,
实为表结构、表数据的复制。
2)、子查询使用在DML中
insert into emp_copy
--values 注意:连values都没有
(
select empno,ename,job,sal,deptno
from emp
);
3)、子查询使用在DQL中
DQL结构
select
from
where
group by 不使用子查询
having
order by 不使用子查询r
子查询的分类
根据子查询的结果,可将子查询分为:
①、单行单列子查询。
select max(sal) from emp
where deptno = 30;--查询30部门的最高工资(1个)
②、多行单列子查询。
select empno from emp
where deptno = 30;--查询30部门的员工编号(多个)
③、多行多列子查询。
select empno,ename,sal,deptno
from emp
where deptno = 30;--查询30部门的员工信息(编号,姓名,工资,部门编号)(多条)
3-1)、子查询使用在where子句中
--查询与JONES员工相同部门的其他员工信息。
--step1:查询JONES员工所在部门
select deptno from emp where ename='JONES';
--step2:部门等于JONES部门的员工(其他员工)
select * from emp where deptno = (step1的结果)
and ename <> 'JONES';
--step3:sql拼接。
select * from emp
where deptno = (
--单行单列子查询
select deptno from emp where ename='JONES'
)
and ename <> 'JONES';
--查询与SMITH、ALLEN不在同一个部门的员工信息。
--step1:查询出SMITH、ALLEN所在部门
select deptno from emp
where ename = 'SMITH' or ename = 'ALLEN';--in ('SMITH'、'ALLEN')
--step2:查询不在SMITH、ALLEN部门的员工
select * from emp
where deptno not in (step1的结果);
--step3:sql拼接
select * from emp
where deptno not in (
--多行单列子查询
select deptno from emp
where ename = 'SMITH' or ename = 'ALLEN'
);
注意:where子句中,可以出现单行单列、多行单列子查询。
单行单列子查询,一般使用 =、!=、<...
多行单列子查询,一般使用 in、any、all。
***补充:
在子查询中,需要引入主查询的某些字段数据。
可以使用exists关键字。
--查询有员工的部门信息
方式一:内连接方式
select d.* from emp e,dept d
where e.deptno = d.deptno;
方式二:使用exists关键字
select * from dept d
where exists --存在以下关系
(
--只需要存在这种关系即可
--能有返回值,说明关系存在
--所以无需关系确切的返回数据内容
select 1 from emp e
where e.deptno = d.deptno
);
3-2)、子查询使用在having子句中
--查收出最低薪水 高于 30部门最低薪水
的部门信息(部门编号、最低薪水)。
--step1:查询出30部门的最低薪水
select min(sal) from emp where deptno=30;
--step2:查询出各部门的最低薪水
select deptno,min(sal)
from emp
group by deptno;
--step3:最低薪水对比
select deptno,min(sal)
from emp
--where 后面无法使用聚合函数
--where min(sal) > (step1的结果)
group by deptno
--但是having可以使用聚合函数
having min(sal) > (step1的结果);
--step4:sql拼接
select deptno,min(sal)
from emp
--where 后面无法使用聚合函数
--where min(sal) > (step1的结果)
group by deptno
--但是having可以使用聚合函数
having min(sal) > (
select min(sal) from emp
where deptno=30
);
3-3)、子查询使用from子句中
from 后面跟 表(多行多列结构)
所以一般多行多列子查询会充当临时表(虚表、匿名视图)
的功能,使用在from后面。
多行多列子查询作为临时表,该表并不存在,
查询到的数据,也只能在当前sql中有效。
--查询与30部门员工职位、工资都相同的
其他部门员工信息。
--step1:先查出30部门的职位及工资
select job,sal from emp
where deptno=30;
--step2:查询其他部门中员工信息
select * from emp
where deptno <> 30;
--step3:职位与工资匹配
select o.*
from (step2结果) o --其他部门人员,
(step1结果) th --30部门职位及工资
where o.job = th.job
and o.sal = th.sal;
--step4:sql
select o.*
from (select * from emp
where deptno <> 30) o, --其他部门人员,
(select job,sal from emp
where deptno=30) th --30部门职位及工资
where o.job = th.job
and o.sal = th.sal;
3-4)、子查询使用在select语句中
把子查询放在select子句中,在一定程度上
可以充当外连接效果。
--查询所有部门部门信息
select distinct d.*,
(select deptno from dept
where deptno not in(
select distinct deptno from emp
where deptno is not null)) noEmpDept
from dept d,emp e
where d.deptno = e.deptno;
或给一个确切的值
select distinct d.*,40 as noEmpDept
from dept d,emp e
where d.deptno = e.deptno;
4、总结:
1)、子查询根据查询结果可分为:
单行单列子查询 (1个值)
多行单列子查询 (多个值)
多行多列子查询 (多条数据)
2)、子查询可以使用在DDL、DML、DQL中。
其中使用在DQL中居多。
3)、一条完整的DQL查询语句,如下:
select
from
where
group by
having
order by
一般 group by、order by后面跟查询表的字段名。
不能乱使用子查询的结果。
select、from、where、having中可以使用子查询。
a、其中where、having后面可以跟上
单行单列子查询 一般使用 =、!=、>、<等关系运算符。
多行单列子查询 一般使用 in、not in、any、all
b、from后面可以跟上
多行多列子查询 充当临时表。
c、select后面只能跟上
单行单列子查询(一般不建议这么用)
补充:
1、删除数据
truncate table emp_copy;--删除数据,保留表结构
delete from emp_copy;--全表删除数据
--truncate、delete的区别:
truncate不需要TCL支持
delete必须TCL支持
2、任何一个大功能sql都是由一个个小功能sql拼起来的。
一定要将功能进行分解,分出一个个小功能。
将小功能先完成,最后做拼接。