Oracle資料庫中的高階查詢以及表連線/內連線/外連線
主要針對以下問題進行講解:
1.列別名和表別名
2.select…from where…group by…having…order by…
3.order by 排序 正序,逆序,單列排序,多列排序
4.rownum rowid Oracle的偽列
5.函式:單行函式(日期函式,字元函式,數學函式,轉換函式,其他),多行函式
6.聚合函式(max ,min avg,sum,count)
7.group by 分組
8.having關鍵字
1.列別名和表別名
加類別名
語法: 欄位名 as 欄位別名
select 'dear '||ename from emp;
針對表中欄位的別名稱為列別名
第一種寫法: select 'dear '||ename as 姓名 from emp;
as 是可以省略的
第二種寫法:別名可以加雙引號 select 'dear '||ename “姓名” from emp;
雙引號可以省略
有一種情況雙引號不能省略:別名中有空格,雙引號不能省略
表別名
語法 : 表名 表別名
–查詢10部門的員工的姓名和工作
select ename,sal,job from emp where deptno=10;
–給emp表一個別名 語法 : 表名 表別名
select e.ename,e.sal,e.job from emp e where e.deptno=10;
select ename,sal,job from emp e where deptno=10; 一張表可以這樣不會出問題,但是多張表後就不可以了。
--規則:一旦給了表別名後,所有欄位的使用都要:表別名.欄位名
-- 注意 :表別名是沒有as的
2.select…from where…group by…having…order by…
注意事項:(1)select ...from...必不可少的 eg:select sysdate from dual; (2)該語句的執行順序,按照這樣的順序where...group by...having...order by... (3)這些關鍵字不能掉換順序,可以沒有,但是如果有的話,是不能掉換順序的
3.order by 排序 正序,逆序,單列排序,多列排序
單列排序
問題:查詢emp表中員工的姓名,工資,按照工資降序排序
select ename,sal from emp order by sal desc;
問題:查詢emp表中員工的姓名,工資,按照工資升序排序
select ename,sal from emp order by sal asc;
asc可以省略,預設情況下就是升序排列
--總結:語法結構:select....from...order by 欄位名 asc/desc
--ASC是升序,desc是降序 如果不寫預設是升序
問題:查詢部門20的員工的姓名和工資,並且按照工資進行降序排序
select ename,sal from emp where deptno=20 order by sal desc;
多列排序
--問題:查詢emp表中的員工的姓名,部門編號,工資,先按照部門進行升序排列,同部門內部按照工資進行降序排列
select ename,deptno,sal from emp where deptno=20 order by deptno asc,sal desc;
多列排序總結:
(1)多列排序語法 order by 欄位名1 asc|desc 欄位名2 asc|desc
(2)多列排序的執行順序,先按照欄位1排序,然後在欄位1排序的基礎上,然後再按照欄位2排序,,,,以此往下
4.rownum rowid Oracle的偽列
rownum
主要是用來做分頁過程(web開發中)**
select *from emp;
select rownum,emp.*from emp; (emp.* 別名)
--rownum 相當於給查詢結果的每一行編一個序列,並沒有儲存在emp表中
select rownum ,e.* from emp e where deptno=30;
--可以看出rownum是動態變化的
問題1:查詢emp表的前五條記錄
select *from emp where rownum<=5;
問題2:查詢emp表中的3-5條記錄
select *from emp where rownum>=3 and rownum<=5; 這樣是查詢不出來的,因為>在rownum是無法使用的
select rownum ro,e.*from emp e where ro>=3 and ro<=5;同樣解決不了。
select * from(select rownum ro,e.*from emp e) where ro>=3 and ro<=5; 這樣就可以使用了(子查詢)
> >=符號是是不管用的
總結:(1)rownum<2 rownum<=2 rownum=1 這樣是可以使用的
--不能是rownum>2或者是rownum>=2 rownum=2
–重點
問題3:查詢emp表中工資最高的前五名的員工姓名,工作,工資
select ename,job,sal from emp where rownum<=5 order by sal desc;
//查詢結果是不正確的,因為只對先進行取前五條,再進行了排序
select *from (select ename,job,sal from emp order by sal desc)x where rownum<=5; 這樣是正確的
要先排序,再取前五行
問題4:查詢emp表中工資最高的3-5名員工的姓名,工作,工資
--分析 --(1)select ename ,job,sal from emp order by sal desc --記為x
--(2)取x得3-5行:select *from (select rownum ro,x.* from x) where ro>=3 and ro<=5;
--(3)替換 select *from (select rownum ro,x.* from (select ename ,job,sal from emp order by sal desc)x) where ro>=3 and ro<=5;
rowid
**:表示的記錄的實體地址,不隨記錄的在查詢結果中的順序的改變而改變,唯一的且固定的
--並沒有寫在表結構中**
select rowid,e.*from emp e;
select rowid ,e.* from emp e where ename='CLARK';
聚合函式(max ,min avg,sum,count)
問題1:求emp表中員工的總數
select count(*) from emp; 求記錄的總數
也可以是這種形式
select count(empno) from emp;
問題2:求emp表中工資最高的那個員工的工資
select max(SAL) FROM EMP;
問題3:求emp表中工資最低的員工的工資
select min(sal) from emp;
問題4:求該公司員工的平均工資
select avg(sal) from emp;
問題5:求該公司每個月一個總開支(工資和獎金)
select sum(sal+comm) from emp; //此處結果有問題 null和數值不能直接相加
select sum(sal+nvl(comm,0)) from emp;
—補充:nvl(comm,0) :判斷comm是否為null 要是null 返回為0,要不是null 返回comm
sum
語法:sum(distinct|all)
引數:all表示對所有的值 (預設),distinct只對不同的值
解釋:求總和
示例:
select sum(distinct sal) from emp;
select sum(all sal) from emp;
avg
語法:avg(distinct|all)
引數:all表示對所有的值 (預設),distinct只對不同的值
解釋:求平均值
示例:
select avg(distinct sal) from emp;
select avg(all sal) from emp;
max
語法:max(distinct|all)
引數:all表示對所有的值 (預設),distinct只對不同的值
解釋:求最大值
示例:
select max(distinct sal) from emp;
min
語法:min(distinct|all)
引數:all表示對所有的值 (預設),distinct只對不同的值
解釋:求最小值
示例:
select min(all sal) from emp;
count
語法:count(distinct|all)
引數:all表示對所有的值 (預設),distinct只對不同的值(相同值只取一次)
解釋:求記錄、資料個數。
示例:
select count(sal) from emp;
select count(distinct sal) from emp;
.group by 分組
問題1:求emp表中每個部門的員工的總人數,請列出部門的編號和總人數,和平均工資
select deptno,count(*),agv(sal) from emp group by deptno;
問題2:求部門10的員工的個數,員工的平均工資,請列出部門的編號和總人數,以及平均工資
--group by 使用規則:
--出現在select後面的欄位,除了聚合函式之外,其他欄位內容必須出現在group by之後
--如果不按照上述規則寫,報錯,不是單組分組函式,使用會出錯。報錯,不是單組函式或者不是group by表示式
問題3:查詢部門10的員工人數和平均工資
select count(*),avg(sal) from emp where deptno=10;
--多欄位分組的一個問題
問題4:查詢emp表中每個部門,每個職位的員工人數;
select deptno,job,count(*) from emp group by deptno,job;
–注意:多欄位分組,分組的順序是按照欄位的先後順序來的
問題5:查詢emp表中,每個部門的編號,並且按照部門人數進行降序排序
select deptno,count() from emp group by deptno order by count() desc;
8.having關鍵字,主要是和group連用,並且針對聚合函式條件進行二次條件限定的
問題6:查詢emp表中每個部門的人數,找出人數大於3的部門,並按照總人數降序排列
select deptno,count() from emp group by deptno having count()>3 order by count(*) desc;
注意事項:
注意事項:(1)聚合函式的條件,不能出現在from ,where子句,不能出現在group by 後面,
聚合函式可以出現在select子句,having子句 order by 子句
(2)where子句中放的是普通條件,不涉及到聚合函式的條件
(3)having 子句中不能放普通條件,涉及聚合函式的條件
高階查詢2
主要針對以下問題進行說明:
1.表連線(內連線,外連線(左外連線,右外連線,全外連線))
2.表連線:兩表連線,三表連線,四表連線
3.子查詢:單行子查詢,多行子查詢
4.子查詢:any all
5.檢視:什麼是檢視?檢視的作用?怎麼建立和刪除檢視?
6.索引:什麼是索引?索引的作用?怎麼建立合適的索引?建立刪除和維護索引語法?
等值連線
--1.問題:查詢每個員工的部門名稱,列出員工姓名和部門名稱
select e.ename,d.dname from emp e,dept d where e.deptno=d.deptno
–表連線中別名的使用:
為了避免出現“未明確定義列”的錯誤,建議使用表別名.欄位名的方式引用欄位
總結:select…from 表1,表2,表3,… where 連線條件1 and 連線條件2 and …
連線條件:e.deptno=d.deptno等值連線的條件,所以這種連線成為等值連線
不等值連線
非等值連線是指在多個表之間使用非等號連線,查詢在多個表中有非等值關聯關係的資料。非等值連線操作符包括>、>=、<、<=、<>以及between…and、like、in等。
例:查詢每個員工的薪水等級
2. 問題:查詢員工表中,每個員工的工資等級,列出員工姓名,工資和工資等級
select e.ename,e.sal,s.grade from emp e,salgrade s
where e.sal between s.losal and s.hisal;
自連線:
自連線是一種特殊的連線,資料的來源是一個表,即關聯關係來自於單表中的多個列。比如職員表中的經理列,就參照了本表中職員編碼列,即經理也是機構下的職員之一。
自連線是通過將表別名虛擬成兩個表的方式實現,可以是等值的或不等值的連線。
例:查詢每個職員經理的名字以及經理的員工編號
--3. 查詢所有比自己領匯入職早的員工的姓名和上級領導的姓名
select w.ename as 員工姓名,m.ename as 上級領導姓名
from emp w,emp m where w.mgr=m.empno and w.hiredate<m.hiredate;
內連線:
--1.問題:查詢每個員工的部門名稱,列出員工姓名和部門名稱
select e.ename,d.dname from emp e inner join dept d on e.deptno=d.deptno;
–總結:select…from 表1 inner join 表2 on 連線條件 where 查詢條件
–問題:查詢部門10中每個員工的工資等級
select e.ename,s.grade from emp e
inner join salgrade s
on e.sal between s.losal and s.hisal --連線條件
where e.deptno=10; --查詢條件
--問題:查詢emp表中部門名稱為ACCOUNTING的員工的姓名,和部門位置
select e.ename,d.loc from emp e,dept d
where e.deptno=d.deptno and d.dname='ACCOUNTING';
select e.ename,d.loc from emp e inner join dept d
on e.deptno=d.deptno
where d.dname='ACCOUNTING';
–查詢高於自己部門平均工資的員工的資訊,列出部門平均工資
--(1)獲得每個部門的平均工資
select deptno,avg(sal) avg_sal from emp group by deptno; --x
--(2) 將x表和emp表做表連線
select e.*,x.* from emp e,x where e.deptno=x.deptno and e.sal>x.avg_sal;
--(3)替換x
select e.*,x.* from
emp e,(select deptno,avg(sal) avg_sal from emp group by deptno)x
where e.deptno=x.deptno and e.sal>x.avg_sal;
內連線和外連線
針對內連線和外連結,我們通過圖表進行詳細說明
A表(父母表):