/*多於兩張表的關聯 如果有多個表參與查詢,先把t1xt2笛卡爾積得到一個大表T1,再把T1xt3笛卡爾積得到一個另外的大表T2,依次類推。 所有的多表查詢最終都是兩種表的查詢。 */ -- 查詢SMITH管理者的薪資等級 select e.ename,m.ename,s.grade from emp e,emp m,salgrade s where 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 e on d.deptno=e.deptno -- 查詢SMITH的上級領導 select e.ename,m.ename from emp e inner join emp m on e.mgr=m.empno where e.ename='SMITH' --使用join on語句連接3張表 -- -- 查詢SMITH的管理者名稱和其管理者的薪資等級 select e.ename,m.ename,s.grade from emp e inner join emp m on e.mgr=m.empno inner join salgrade s on m.sal between s.losal and s.hisal where e.ename='SMITH' --99外連接 /*外連接在99語法中通過outer 關鍵字,按照主從表的位置可以分為left outer/right outer, 語法 select filed1,field2 from 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_list FROM table WHERE expr operator (SELECT select_list FROM table); 解子查詢的關鍵在於把子查詢當作一張表來看待。外層的語句可以把內嵌的子查詢返回的結果當成一張表使用。子查詢可以作為一個虛表被使用。 子查詢要用括號括起來 將子查詢放在比較運算符的右邊(增強可讀性) 子查詢根據其返回結果可以分為單行子查詢和多行子查詢。 */ ----------------單行子查詢 --當子查詢有單行時,可以取單行中的一個字段形成單個值用於條件比較。 -- 查詢雇員其薪資在雇員平均薪資以上 -- [1] 查詢員工的平均薪資 select avg(e.sal) "AVGSAL" from emp e --[2] 查詢滿足條件的雇員 select * from emp e1 where e1.sal>(select avg(e.sal) "AVGSAL" from emp e) ---------------------多行子查詢 -- 查在雇員中有哪些人是管理者 --【1】查詢管理者 select distinct e.mgr from emp e where e.mgr is not null --【2】查詢指定列表的信息 in select e.* from emp e where e.empno in (select distinct e.mgr from emp e where e.mgr is not null) -- 部門編號為20的所有員工中收入最高的職員 -- [1]查詢部門為20的雇員的所有工資 select e.sal from emp e where e.deptno=20 --[2] 部門編號為20的所有員工中收入最高的職員 select e.* from emp e where 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 e group by e.deptno --【2】求等級 select vt.deptno,vt.avgsal,s.grade from (select e.deptno,avg(e.sal) "AVGSAL" from emp e group by e.deptno ) VT,salgrade s where vt.avgsal between s.losal and s.hisal --求平均薪水 最高的部門的 部門編號 select vt.deptno,vt.avgsal from(select e1.deptno,avg(e1.sal) "AVGSAL" from emp e1 group by e1.deptno) VT where vt.avgsal=(select max(vt.avgsal) from(select avg(e.sal) "AVGSAL" from emp e group by e.deptno) VT) -------------TOP-N /*把select得到的數據集提取前n條數。 rownum:表示對查詢的數據集記錄的編號,從1開始。*/ -- 查詢前10名雇員 select e.*,rownum from emp e where rownum<=10 ---------- 查詢按照薪資降序,前10名雇員 select vt.* from (select e.* from emp e order by e.sal desc) VT where 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) VT0 where vt0.rn >= (n-1)*size+1 */ -- -- 查詢6-10號的雇員 select vt.* from (select e.*,rownum "RN" from emp e where rownum<=10) VT where 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 t group by t.name
