oracle:多表關聯 join on,單行子查詢,多行子查詢,TOP-N,行轉列


/*多於兩張表的關聯
如果有多個表參與查詢,先把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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM