1. 程式人生 > 其它 >Oracle多表關聯

Oracle多表關聯

1. 92語法多表關聯

1.1笛卡爾積

-- 笛卡爾積
select *
from emp,dept

1.2等值連線

-- 等值連線
-- 需求:查詢僱員的部門名稱
select e.ename,e.deptno,d.dname
from emp e,dept d
where e.deptno = d.deptno

1.3不等值連線

-- 不等值連線
-- 查詢每個僱員的薪資等級
select e.ename,e.sal,sg.grade
from emp e,salgrade sg
where e.sal >= sg.losal and e.sal <= sg.hisal
-- where e.sal between sg.losal and sg.hisal

1.4外連線

左外連線:左邊的表作為主表,右邊表作為從表,主表資料都顯示,從表資料沒有,用null填充,用+號表示。

-- 左外連線(B)
-- 需求:查詢所有部門的僱員
select *
from dept d,emp e
where d.deptno = e.deptno(+)

右外連線: 右邊的表作為主表,左邊表作為從表,主表資料都顯示,從表資料沒有,用null填充,用+號表示。

-- 右外連線(B)
select *
from emp e,dept d
where e.deptno(+) = d.deptno;

1.5自連線

-- 查詢每個僱員的上級領導
select e.ename "僱員",m.ename "領導"
from emp e,emp m
where e.mgr = m.empno

-- 優化king
select e.ename "僱員",nvl(m.ename,'boss') "領導"
from emp e,emp m
where e.mgr = m.empno(+)

1.6多餘兩張表的連線

如果有多個表參與查詢,先把t1xt2笛卡爾積得到一個大表T1,再把T1xt3笛卡爾積得到一個另外的大表T2,依次類推。

所有的多表查詢最終都是兩種表的查詢。

-- 查詢SCO%T管理者的薪資等級
select e.ename,m.ename,sg.grade
from emp e,emp m,salgrade sg
where e.mgr = m.empno and (m.sal between sg.losal and sg.hisal) and e.ename = 'SCO%T'

-- 查詢僱員Scott所在部門名稱和薪資等級
select e.*,d.*,sg.*
from emp e,dept d,salgrade sg
where e.deptno = d.deptno and e.sal between sg.losal and sg.hisal
and e.ename = 'SCO%T'

2.99語法多表關聯

92語法的主要問題:

[1]表的過濾條件和表的連線條件混合在一起,維護麻煩

[2]資料庫的資料適合變化,根據where子句的執行規則,sql語言也會相應發生變化,給維護造成一定成本。

2.1笛卡爾積

-- 99 笛卡爾積
select *
from dept d cross join emp e

2.2自然連線

NATURAL JOIN子句基於兩個表中列名完全相同的列產生連線

[1]兩個表有相同名字的列

[2]資料型別相同

[3]從兩個表中選出連線列的值相等的所有行

-- [2]自然連線
select *
from dept d natural join emp e

注意:自然連線最優的使用場景是:主外來鍵關係且主外來鍵欄位只有一個。

2.3using關鍵字

using 主要用於指定連線欄位。

[1] 按照指定的欄位連線兩個表。

[2] 選指定欄位值相同的資料行。

2.4on關鍵字指定連線條件

自然連線的條件是基於表中所有同名列的等值連線,為了設定任意的連線條件或者指定連線的列,需要使用ON子句連個表的關聯用關鍵字 join ,預設內連線(inner) 語法

select filed1,fild2,…
from table1 
join table2 on condition1
     [join table3 on condition2]*
-- 查詢出員工的部門名稱
select *
from dept d join emp e
on d.deptno = e.deptno
-- 查詢scott的上級領導
select e.ename,m.ename
from emp e join emp m
on e.mgr = m.empno
where e.ename = 'SCO%T'

2.5使用jion on 連線3張表

-- 查詢SCO%T部門名稱和薪資等級
select e.ename,d.dname,sg.grade
from dept d join emp e on d.deptno = e.deptno 
join salgrade sg on e.sal between sg.losal and sg.hisal
where e.ename = 'SCO%T'
-- 查詢SCO%T的管理者名稱和其管理者的薪資等級
select e.ename,m.ename,sg.grade
from emp e join emp m on e.mgr = m.empno
join salgrade sg on m.sal between sg.losal and sg.hisal
where e.ename = 'SCO%T'

2.6外連線

外連線在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;

3.子查詢

sql中查詢是可以巢狀的。一個查詢可以作為另外一個查詢的條件、表。

SELECT    select_list
FROM    table
WHERE    expr operator
        (SELECT    select_list
             FROM    table);

3.1單行子查詢

當子查詢有單行時,可以取單行中的一個欄位形成單個值用於條件比較。

-- 查詢僱員其薪資在僱員平均薪資以上
-- [1] 查詢員工的平均薪資
select avg(e.sal) "AVGSAL"
from emp e

--[2] 查詢滿足條件的僱員
select *
from emp e
where e.sal > (select avg(e.sal) "AVGSAL" from emp e)

3.2多行子查詢

-- 查在僱員中有哪些人是管理者
--【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)

多行子查詢返回的結果可以作為 表 使用,通常結合in、some/any、all、exists。

3.3from後的子查詢

-- 每個部門平均薪水的等級
--【1】部門的平均薪資
select e.deptno,avg(e.sal) "AVGSAL"
from emp e
group by e.deptno

--【2】求等級
select vt0.deptno,vt0.avgsal,sg.grade
from (select e.deptno,avg(e.sal) "AVGSAL"
        from emp e
        group by e.deptno) VT0,salgrade sg
where vt0.avgsal between sg.losal and sg.hisal
-- 99 join on
select vt0.deptno,vt0.avgsal,sg.grade
from (select e.deptno,avg(e.sal) "AVGSAL"
        from emp e
        group by e.deptno) VT0 join salgrade sg on vt0.avgsal between sg.losal and sg.hisal

3.4TOP-N

把select得到的資料集提取前n條數。

rownum:表示對查詢的資料集記錄的編號,從1開始。

-- 查詢前10名僱員
select e.*,rownum
from emp e
where rownum <= 10

rownum和order-by:

--查詢按照薪資降序,前10名僱員

select vt0.*,rownum

from (select e.*

from emp e

order by e.sal desc) VT0

where rownum <= 10

總結

[1] order by 一定在整個結果集出現後才執行。

[2] rownum 在結果集出現後才有編號。

3.5分頁

-- 求查詢6-10號的僱員
select vt0.*
from (select e.*,rownum "RN"
        from emp e 
        where rownum <= 10) VT0
where vt0.rn >= 6

求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

3.6行轉列

要想從上表中得到類似下面的結果:

姓名 語文 數學 英語

張三 78 88 98

王五 89 56 89

select ts.name,
sum(decode(ts.subject,'語文',ts.score)) "語文",
sum(decode(ts.subject,'數學',ts.score)) "數學",
sum(decode(ts.subject,'英語',ts.score)) "英語"
from test_score ts
group by ts.name