/*多于两张表的关联如果有多个表参与查询,先把t1xt2笛卡尔积得到一个大表T1,再把T1xt3笛卡尔积得到一个另外的大表T2,依次类推。所有的多表查询最终都是两种表的查询。*/-- 查询SMITH管理者的薪资等级select e.ename,m.ename,s.gradefrom emp e,emp m,salgrade swhere e.mgr=m.empno and (m.sal between s.losal and s.hisal)and e.ename='SMITH'------------------多表关联(A) - 99 语法/*92的问题:[1]表的过滤条件和表的连接条件混合在一起,维护麻烦[2]数据库的数据适合变化,根据where子句的执行规则,sql语言也会相应发生变化,给维护造成一定成本。语法:-- 99 笛卡尔积select *from dept d cross join emp e*/----------------自然连接/*NATURAL JOIN子句基于两个表中列名完全相同的列产生连接[1]两个表有相同名字的列[2]数据类型相同[3]从两个表中选出连接列的值相等的所有行注意:自然连接最优的使用场景是:主外键关系且主外键字段只有一个。*/-- 自然连接(自然连接只保留一个重复列)select *from dept d natural join emp e-----------using/*using 主要用于指定连接字段。[1] 按照指定的字段连接两个表。[2] 选指定字段值相同的数据行。using 同样适用于自然连接。*/---------------------------on 指定连接条件/*自然连接的条件是基于表中所有同名列的等值连接为了设置任意的连接条件或者指定连接的列,需要使用ON子句连个表的关联用关键字 join ,默认内连接(inner) 语法select filed1,fild2,…from table1 join table2 on condition1 [join table3 on condition2]* */-- 查询出员工的部门名称select *from dept d inner join emp eon d.deptno=e.deptno-- 查询SMITH的上级领导select e.ename,m.enamefrom emp e inner join emp mon e.mgr=m.empnowhere e.ename='SMITH'--使用join on语句连接3张表---- 查询SMITH的管理者名称和其管理者的薪资等级select e.ename,m.ename,s.gradefrom emp e inner join emp m on e.mgr=m.empnoinner join salgrade s on m.sal between s.losal and s.hisalwhere e.ename='SMITH'--99外连接/*外连接在99语法中通过outer 关键字,按照主从表的位置可以分为left outer/right outer,语法select filed1,field2from table1 left/right outer join table2 on condition1 [left/right outer join table3 on condition2]**/-------------左外连接--------------查询所有部门的所有员工select *from dept d left outer join emp e on d.deptno = e.deptno---右外连接select * from emp e right outer join dept d on e.deptno = d.deptno--------------------------------子查询---sql中查询是可以嵌套的。一个查询可以作为另外一个查询的条件、表。/*SELECT select_listFROM tableWHERE expr operator (SELECT select_list FROM table); 解子查询的关键在于把子查询当作一张表来看待。外层的语句可以把内嵌的子查询返回的结果当成一张表使用。子查询可以作为一个虚表被使用。子查询要用括号括起来 将子查询放在比较运算符的右边(增强可读性)子查询根据其返回结果可以分为单行子查询和多行子查询。 */----------------单行子查询--当子查询有单行时,可以取单行中的一个字段形成单个值用于条件比较。-- 查询雇员其薪资在雇员平均薪资以上-- [1] 查询员工的平均薪资select avg(e.sal) "AVGSAL"from emp e--[2] 查询满足条件的雇员select *from emp e1where e1.sal>(select avg(e.sal) "AVGSAL" from emp e)---------------------多行子查询-- 查在雇员中有哪些人是管理者--【1】查询管理者select distinct e.mgrfrom emp ewhere e.mgr is not null--【2】查询指定列表的信息 inselect e.*from emp ewhere e.empno in (select distinct e.mgrfrom emp ewhere e.mgr is not null)-- 部门编号为20的所有员工中收入最高的职员-- [1]查询部门为20的雇员的所有工资select e.sal from emp e where e.deptno=20--[2] 部门编号为20的所有员工中收入最高的职员select e.*from emp ewhere e.sal>=all(select e.sal from emp e where e.deptno=20) and e.deptno=20-----多行子查询返回的结果可以作为 表 使用,通常结合in、some/any、all、exists。-------------From后的子查询---子查询可以作为一张续表用于from后。-- 每个部门平均薪水的等级--【1】部门的平均薪资select e.deptno,avg(e.sal) "AVGSAL"from emp egroup by e.deptno--【2】求等级select vt.deptno,vt.avgsal,s.gradefrom (select e.deptno,avg(e.sal) "AVGSAL"from emp egroup by e.deptno) VT,salgrade swhere vt.avgsal between s.losal and s.hisal--求平均薪水 最高的部门的 部门编号select vt.deptno,vt.avgsalfrom(select e1.deptno,avg(e1.sal) "AVGSAL"from emp e1group by e1.deptno) VTwhere vt.avgsal=(select max(vt.avgsal) from(select avg(e.sal) "AVGSAL"from emp egroup by e.deptno) VT)-------------TOP-N/*把select得到的数据集提取前n条数。rownum:表示对查询的数据集记录的编号,从1开始。*/-- 查询前10名雇员select e.*,rownumfrom emp ewhere rownum<=10---------- 查询按照薪资降序,前10名雇员select vt.*from (select e.*from emp eorder by e.sal desc) VTwhere rownum <=10/*总结[1] order by 一定在整个结果集出现后才执行。[2] rownum 在结果集出现后才有编号。。。。-> select -> rownum -> order by*/-------------------分页/*求page=n,pagesize=size的数据=>[(n-1)*size+1,n*size]select vt0.*from (select t.*, rownum “RN”from table t where rownum <= n*size) VT0where vt0.rn >= (n-1)*size+1*/-- -- 查询6-10号的雇员select vt.*from (select e.*,rownum "RN" from emp e where rownum<=10) VTwhere vt.rn>=6----------------------行转列create table test_score( name VARCHAR2(20), subject VARCHAR2(20), score NUMBER(4,1))insert into test_score (NAME, SUBJECT, SCORE) values ('张三', '语文', 78.0);insert into test_score (NAME, SUBJECT, SCORE) values ('张三', '数学', 88.0);insert into test_score (NAME, SUBJECT, SCORE) values ('张三', '英语', 98.0);insert into test_score (NAME, SUBJECT, SCORE) values ('李四', '语文', 89.0);insert into test_score (NAME, SUBJECT, SCORE) values ('李四', '数学', 76.0);insert into test_score (NAME, SUBJECT, SCORE) values ('李四', '英语', 90.0);insert into test_score (NAME, SUBJECT, SCORE) values ('王五', '语文', 99.0);insert into test_score (NAME, SUBJECT, SCORE) values ('王五', '数学', 66.0);insert into test_score (NAME, SUBJECT, SCORE) values ('王五', '英语', 91.0);select * from test_score ;-- 行转列问题select t.name,sum(decode(t.subject,'语文',t.score)) "语文",sum(decode(t.subject,'数学',t.score)) "数学",sum(decode(t.subject,'英语',t.score)) "英语"from test_score tgroup by t.name