-- 内连接-- 举例:查询员工表和部门表的记录-- 笛卡尔积:员工表中的任意一条记录要和部门表中的每一条记录相关联select * from emp ,dept ;-- 避免笛卡尔积: 设置条件(从表中外键=主表主键)select * from emp ,dept where emp.deptno = dept.deptno;select * from emp e , dept d where e.deptno = d.deptno;-- 举例:查询员工的上级领导select * from emp e, emp m where e.mgr = m.empno;-- 举例:在上面的基础上:查询员工的部门名称select e.empno ,e.ename,d.dname ,'||',m.empno ,m.ename
from emp e, emp m ,dept d
where e.mgr = m.empno and e.deptno = d.deptno;-- 举例:在上面的基础上:查询领导的部门名称select e.empno ,e.ename,d.dname ,'||',m.empno ,m.ename,d2.dname
from emp e, emp m ,dept d ,dept d2
where e.mgr = m.empno and e.deptno = d.deptno
and m.deptno = d2.deptno;-- 举例:在上面的基础上,查询员工和领导的工资等级select e.empno ,e.ename,d.dname ,s1.grade,'||',m.empno ,m.ename,d2.dname ,s2.grade
from emp e, emp m ,dept d ,dept d2, salgrade s1 ,salgrade s2
where e.mgr = m.empno and e.deptno = d.deptno
and m.deptno = d2.deptno
and e.sal between s1.losal and s1.hisal
and m.sal between s2.losal and s2.hisal;-- 条件表达式-- case when/*
case 表达式
when 值 then 返回值
when 值 then 返回值
when 值 then 返回值
when 值 then 返回值
....
else 返回值
end
*/-- 举例:当输入1时,返回一 ,输入2时,返回二....selectcase3when1then'一'when2then'二'else'其他'endfrom dual;select e.empno ,e.ename,d.dname ,
case s1.grade
when1then'一级'when2then'二级'when3then'三级'when4then'四级'else'其他'end 员工工资等级
,'||',m.empno ,m.ename,d2.dname ,s2.grade
from emp e, emp m ,dept d ,dept d2, salgrade s1 ,salgrade s2
where e.mgr = m.empno and e.deptno = d.deptno
and m.deptno = d2.deptno
and e.sal between s1.losal and s1.hisal
and m.sal between s2.losal and s2.hisal;-- decode-- decode(表达式 ,key,value ,key,value,...., elsevalue)select e.empno ,e.ename,d.dname ,
case s1.grade
when1then'一级'when2then'二级'when3then'三级'when4then'四级'else'其他'end 员工工资等级
,'||',m.empno ,m.ename,d2.dname ,
decode(s2.grade ,4,'四级',5,'五级','其他')领导的工资等级
from emp e, emp m ,dept d ,dept d2, salgrade s1 ,salgrade s2
where e.mgr = m.empno and e.deptno = d.deptno
and m.deptno = d2.deptno
and e.sal between s1.losal and s1.hisal
and m.sal between s2.losal and s2.hisal;
二、外连接
-- 外连接:能显示基准表中所有的记录-- 举例:查询员工的上级领导--左外连接:select * from 左表 left join 右表 on 条件select e.empno ,e.ename,m.empno ,m.ename
from emp e leftjoin emp m
on e.mgr = m.empno;--右外连接:select * from 左表 right join 右表 on 条件select e.empno ,e.ename,m.empno ,m.ename
from emp m rightjoin emp e
on e.mgr = m.empno;--全外连接(了解):select * from 左表 full join 右表 on 条件select e.empno ,e.ename,m.empno ,m.ename
from emp m fulljoin emp e
on e.mgr = m.empno;--特殊外连接:由内连接改造来的-- (+) : 显示对方表中的所有记录select e.empno ,e.ename,m.empno ,m.ename
from emp e , emp m
where e.mgr = m.empno(+);
三、子查询
子查询:在一条sql语句中包含另一条sql查询语句
-- 外查询 内查询-- 举例:查询与7876工作一样的员工select * from emp where job = (select job from emp where empno = 7876);-- 举例:查询存在员工的部门信息-- 先查询存在员工部门编号selectdistinct deptno from emp ;-- 查询部门的信息: in(set): set 必须是一个固定的集合,或者是一个一列多行的结果集select * from dept where deptno in (10,20,30);select * from dept where deptno =any (10,20,30);-- =some-- 标准的语句select * from dept where deptno in (selectdistinct deptno from emp);-- 查询每个部门的最低工资的员工信息-- 先查询每个部门的最低工资selectmin(sal) minsal,deptno from emp groupby deptno;-- 查询员工信息:如果结果集是多行多列,作为一张表使用,必须取别名select e.empno ,e.ename ,e.sal ,e.deptno, t.minsal ,t.deptno
from emp e,(selectmin(sal) minsal,deptno from emp groupby deptno) t
where e.deptno = t.deptno and t.minsal = e.sal;-- 查询与7790工作一样的员工信息select * from emp where job = (select job from emp where empno = 7790);-- 子查询小结-- 返回一个值:可以使用 = != <> <= >=-- 返回一列多行:使用in ,=any ,=some -- 返回多行多列:把结果集作为表使用-- 返回null: 不会报错
四、exists运算符
-- exists 运算符(效率较高):存在 ,只会返回两个值:true ,falseselect * from emp whereexists (select * from emp where empno = 7788);select * from emp where1=1;select * from emp whereexists (select * from emp where empno = 8890);select * from emp where1=2;-- 举例:查询存在员工的部门信息select * from dept where deptno in (selectdistinct deptno from emp);select * from dept d whereexists (select * from emp e where e.deptno = d.deptno);
五、分页
-- 伪列: --rowid 行编号: 在添加记录时生成,存储的内存地址select e.*,rowid from emp e where rowid= 'AAAMfPAAEAAAAAgAAA';-- rownum : 行号,每加载一条记录生成一个行号,行号是从1 开始,依次递增,每次递增一个 -- 分页select e.*,rownum from emp e;-- 举例:查询员工表的前三条记录select e.*,rownum from emp e where rownum <= 3;-- 举例:查询员工表的4-6条记录-- 先生成行号select e.*,rownum from emp e
-- 把结果集作为表使用,做条件筛选
select t.*
from (select e.*,rownum rn from emp e) t
where t.rn between 4and6;-- 举例: 查询工资最高的前三名-- 先工资的降序排序select e.* from emp e orderby sal desc;-- 把结果集作为表使用,再生成行号select t.*
from (select e.* from emp e orderby sal desc) t
where rownum <= 3
-- 举例: 查询工资最高的 4 - 6名
-- 先按照工资的降序排序
select e.* from emp e orderby sal desc
-- 作为表示用,生成行号
select t.* ,rownum rn from (select e.* from emp e orderby sal desc) t
-- 作为表示用,条件筛选
select m.*
from (select t.* ,rownum rn from (select e.* from emp e orderby sal desc) t) m
where m.rn between 4and6;-- 分析函数: row_number() over(排序语句)select t.*
from (select e.* ,row_number() over(orderby sal desc) rn from emp e) t
where t.rn between 4and6;
六、练习
-- 查询员工的薪水大于本部门平均薪水的员工-- 先查询每个部门的平均薪水selectavg(sal) , deptno from emp groupby deptno;-- 条件筛选select e.empno ,e.ename ,e.sal ,e.deptno , t.avgsal ,t.deptno
from emp e ,(selectavg(sal) avgsal , deptno from emp groupby deptno) t
where e.deptno = t.deptno and e.sal > t.avgsal;-- 查询每年入职的员工个数selectcount(1),to_char(hiredate ,'yyyy') hireyear from emp groupby to_char(hiredate ,'yyyy');-- 行列转换selectsum(c) "Total",
avg(decode(hireyear ,'1980',c)) "1980",
avg(decode(hireyear ,'1981',c)) "1981",
avg(decode(hireyear ,'1982',c)) "1982",
avg(decode(hireyear ,'1987',c)) "1987"from (selectcount(1) c,to_char(hiredate ,'yyyy') hireyear
from emp groupby to_char(hiredate ,'yyyy')) t
七、集合运算符
-- 交集select * from emp where deptno = 20intersectselect * from emp where job = 'CLERK';select * from emp where deptno = 20and job = 'CLERK';-- 并集: union all 不会去除重复的记录-- union会去除重复的记录 , 会触发索引select * from emp where deptno = 20unionselect * from emp where job = 'CLERK';-- 不会触发索引select * from emp where deptno = 20or job = 'CLERK';-- 差集: A B-- 在A集合中出现的,在B集合中没有出现select * from emp where deptno = 20
minus
select * from emp where job = 'CLERK';select * from emp where job = 'CLERK'
minus
select * from emp where deptno = 20;-- 前提:两个集合:类型,顺序,个数一致即可 select empno ,ename from emp where deptno = 20unionselect deptno ,dname from dept;
八、递归查询
--- 递归查询(单表的递归查询)(了解)-- 语法:/*
select * from 表
条件一: 设置起始位置
start with 条件
条件二: 设置关联条件,设置方向
connect by 条件;
*/-- 查询某员工的领导信息,领导的领导信息,....select * from emp
startwith empno = 7369connectbyprior mgr = empno;-- 查询某员工的下属员工,下属的下属,....select * from emp
startwith empno = 7839connectby mgr = prior empno;