查詢是數據的一個重要操作。用戶發送查詢請求,經編譯軟件變異成二進制文件供服務器查詢,后返回查詢結果集給用戶,查詢會產生一個虛擬表,看到的是表形式顯示的結果,但結果并不真正的存儲,每次執行查詢只是從數據表中提取數據,并按照表的形式顯示出來。
SELECT <列名>
FGROM <表名>
[WHERE <查詢條件表達式>]
[GROUP BY <分組表達式>]
[HAVING <分組查詢表達式>]
[ORDER BY <排序的列名> [ASC或DESC]]
group by
group by 用于對查詢的結果分組統計,通過對group by后面的名字進行分組后輸出結果。
select deptno,count(ename) from emp group by deptno;
統計公司每個部門的員工人數
select deptno,avg(sal),max(sal) from emp group by deptno;
顯示每個部門的平均工資和最高工資
select deptno,gender,count(ename) from emp group by deptno,gender;
按照性別統計各個部門人數//需要手動添加一個gender列,并添加屬性
group by后面還可以跟多列表示多列分組,在多列分組時放前面的優先分組。
group by 列名,列名
select count(*) as 人數,deptno as 部門號,job 工作 from emp group by deptno,job order by deptno;
having
having 子句用于限制分組顯示結果,其只能和group by一起連用。在where中沒有辦法直接使用聚合函數,即sum avg等無法使用,所以引用了having,在having中可以使用這些函數。
select deptno,avg(sal) from emp group by deptno having avg(sal)<2000;
顯示工資低于2000的部門號和它的平均工資
select deptno as 部門號,count(*) as 人數 from emp group by deptno having count(*)>4;
顯示部門人數大于4的部門
order by
order by 表示排序,后跟列名和排序方式。如果什么都不加默認為升序。ASC表示升序,DESC表示降序。
select empno,ename,sal from emp order by sal;
select empno,ename,sal from emp order by sal asc;
select empno,ename,sal from emp order by sal desc;
在Oracle中還可以設置多列排序
order by 列名1 升降,列名2 升降;
前面的為主要排序,后面的為次一級排序。
注:碰到自己與自己比較的情況下,不能用having,可以創建一個新列。
select depton,count(deptno) from emp group by deptno having sal>avg(sal);
select emp.deptno,count(*) from emp,(select deptno,avg(sal) avgsal from emp group by deptno) a where emp.deptno=a.deptno and emp.sal>a.avgsal group by emp.deptno;
查詢每個部門中工資高于該部門平均工資的員工人數
注:如果select語句同時包含group by,having,order by,按group by,having,order by排序
分組和聚合一起使用,目的是為了統計信息。
where是為了from服務的,只能跟真實的字段,用來篩選from子句中指定的操作所產生的行
group by 用來分組where子句的輸出
having 用來從分組的結果中篩選行
order by用來對篩選的結果進行排序
復雜查詢
(1)分組函數:max min?avg sum count
max表示該列的最大值,min表示該列的最小值,avg表示該列的平均值,sum表示該列的和,count表示該列的行數。
注:分組函數(max、min、avg、count、sum)只能出現在選擇列表中having子句、order by子句、不能出現在where子句和group by子句中。
select max(sal),min(sal) from emp;
如何顯示所有員工最高工資和最低工資
select avg(sal),sum(sal) from emp;
顯示所有員工的平均工資和工資總和
select count(ename) from emp; //count用于計算行
計算共有多少員工
select ename,job from emp where sal=(select max(sal) from emp);
顯示工資最高的員工的名字,工作崗位(max等沒辦法直接跟在where后面)
select ename,sal from emp where sale>(select avg(sal) from emp);
顯示工資高于平均員工信息
(2)多表查詢
多表查詢是指兩個和兩個以上的表或者是視圖的查詢,在實際應用中,當查詢單個表不能滿足需求時,一般使用多表查詢。如:顯示sales部門位置和其員工的姓名,這種情況下需要使用到(dept表和emp表)。
多表查詢的連接一般可以分為:內連接、左外連接、右外連接、全連接。
注:在使用多表查詢的時候每個表可以設置別名,如果表指定了別名,那么語句中所有語句必須使用別名,而不能再使用實際表名。且在寫屬性的時候如果屬性為其中一個表特有的屬性則不需要寫別名,如果是兩個表都有則必須指定是哪一個表的哪個屬性格式為:表名.屬性名。
select 列名 from 表1 別名,表2 別名...
select d.loc,e.ename,e.job from emp e,dept d where e.deptno=d.deptno
注:e是emp的別名,d是dept的別名。
但如果對表進行了操作則需要設置別名,如:查詢每個部門中工資高于該部門平均工資的員工人數。在其中有一個avg表,這個表必須設置別名(提醒:如果僅有一個被修改的表,則可以不設置別名,但如果有多個表則必須設置別名)。
select emp.deptno,count(*) from emp,(select deptno,avg(sal) avgsal from emp group by deptno) a where emp.deptno=a.deptno and emp.sal>a.avgsal group by emp.deptno;
內連接
內連接通過使用比較運算符來使每個表的通用列中的值匹配來組成一個新表,即:把兩個表中間共有的那些行拿出來進行連接,如果某些行不是兩個表共有的,則不進行連接。
select
from 表1
inner join 表2
on 匹配條件
或
select
from 表1 表2
where匹配條件
select * from emp,dept where emp.deptno=dept.deptno;
select emp.ename,emp.sal,dept.dname from emp,dept where emp.deptno=dept.deptno;
左外連接
左外連接與內連接的區別是:設置左外連接的時候設置了主表和附表,主表在前,附表在后。內連接是將兩個表匹配的地方輸出出來,而左外連接則是主表全寫,附表一一對應,附表有則加上,沒有不寫。
select
from 表1
left join 表2
on 匹配條件
select e.ename,e.job,d.loc from dept d left join emp e on d.deptno=e.deptno;
將dept表放在前面,以dept表為主表,emp表做輔表進行鏈接
select e.ename,d.dname,d.loc from emp e left join dept d on e.deptno=d.deptno;
將emp表放在前面,是以emp表作為主表,dept表作為輔表進行鏈接
右外連接
右外連接和左外連接基本相同只是右外連接的主表寫在后邊。
select
from 表1
right join 表2
on 匹配條件
select e.ename,d.loc from emp e right join dept d on e.deptno=d.deptno;
這個dept表放在后面,以dept表為主表,emp做輔表進行鏈接
select dname,ename,sal from dept left join emp on dept.deptno=emp.deptno;
查詢每個部門下的員工的姓名,工資
全連接
全連接是在等值連接的基礎上將左表和右表的未匹配數據都加上,使用的關鍵字為full outer join或者full join。
select
from 表1
full join 表2
on 匹配條件
select e.ename,d.loc from emp e full join dept d on e.deptno=d.deptno;
自連接
還有一種特殊情況即自連接,在Oracle中一個表無法與自己進行比較,所以當需要自己表的兩個信息做比較的時候也需要使用連接來連接,即同一張表的連結查詢。
select a.ename 員工,b.ename 領導 from emp a,emp b where a.mgr=b.empno;
select a.ename 員工,b.ename 領導 from emp a left join emp b on a.mgr=b.empno;
(3)子查詢
子查詢是指嵌套在其他sql語句中的select語句,也叫嵌套查詢。sql語句執行順序為從右到左執行,所以在執行查詢時會先執行左側的子查詢后進行主查詢。
子查詢分為單行子查詢和多行子查詢,單行子查詢是指返回一行數據的子查詢語句,多行子查詢是指返回多行數據的查詢語句。子查詢還可以分為多列子查詢、多行子查詢、多列多行子查詢。
在進行子查詢時如果內部查詢不返回任何記錄,則外部條件中字段DEPTNO與NULL比較永遠為假,也就是說外部查詢不返回任何結果。
總結為:
單行子查詢是指子查詢只返回單列、單行數據
多行子查詢是指返回單列多行數據,都是針對單列而言的
多列子查詢則是指查詢返回多個列數據的子查詢語句
單行子查詢
where deptno = (單行數值)
多行子查詢
where deptno in ( 多行數值 )
多列子查詢:
where (job,deptno)=(select job,deptno from emp where ename='KING')
多列多行子查詢
where (job,deptno) in (select job,deptno from emp where ename='KING')
單行子查詢
在單行子查詢的外部查詢中可以使用=、>、<、>=、<=、<>等比較運算符。
內部查詢返回的結果必須與外部查詢條件中字段(DEPTNO)相匹配。
select ename from emp where deptno=(select deptno from emp where ename='SMITH');
查詢和SMITH部門相同的員工的名字
select ename,job,sal from emp where deptno=(select deptno from dept where dname='SALES');
查詢出銷售部(SALES)下面的員工姓名,工作,工資
select emp.deptno,count(*) from emp,(select deptno,avg(sal) avgsal from emp group by deptno) a where emp.deptno=a.deptno and emp.sal>a.avgsal group by emp.deptno;
查詢每個部門中工資高于該部門平均工資的員工人數
多行子查詢
在WHERE子句中使用多行子查詢時,可以使用多行比較運算符(IN,ALL,ANY)。
IN:等于任何一個。
ALL:和子查詢返回的所有值比較。例如:sal>ALL(1,2,3)等價于sal>3,即大于所有。
ANY:和子查詢返回的任意一個值比較。例如:sal>ANY(1,2,3)等價于sal>1,即大于任意一個就可以。
注:ANY運算符必須與單行比較運算符結合使用,并且返回行只要匹配子查詢的任何一個結果即可。
select ename,sal,deptno from emp where sal>any(select sal from emp where deptno=30);
如何顯示工資比部門30的任意一個員工的工資高的員工的姓名、工資和部門號
還可以:select ename,sal,deptno from emp where sal > (select min(sal) from emp where deptno=30);
select ename,sal,deptno from emp where sal > all(select sal from emp where deptno=30);
顯示工資比部門30的所有員工的工資高的員工的姓名、工資和部門號
select * from emp where job in(select job from emp where ename='MARTIN' or ename='SMITH');
查詢emp表中工作和MARTIN和SMITH工作相同的員工的信息
select ename,hiredate from emp where deptno=(select deptno from emp where ename='BLAKE') and ename<> 'BLAKE';
創建一個查詢,顯示與blake在同一部門工作的雇員的姓名和受雇日期,black不包含在內
select ename,sal,mgr from emp where mgr=(select empno from emp where ename='KING');
顯示被king直接管理的雇員的姓名以及工資
多列子查詢
多列子查詢和多行子查詢相同,只是使用多列子查詢的時候會有多列進行匹配。
如何查詢與smith的部門和崗位完全相同的所有雇員
select ename,job,deptno from emp where (deptno,job)=(select deptno,job from emp where ename='SMITH');
select ename,job,deptno from emp where (deptno,job) in (select deptno,job from emp where ename='SMITH');
(4)集合運算
為了合并多個select語句的結果,可以使用集合操作符號union,union all,intersect,minus。
union:該操作符用于取得兩個結果集的并集。當使用該操作符時,會自動去掉結果集中重復行
select ename,sal,job from emp where sal>2500 union select enmae,sal,job from emp where job='manager';
union all:該操作與union相似,但是它不會取消重復行,而且不會排序
select ename,sal,job from emp where sal>2500 union all select ename,sal,job from emp where job='manager';
intersect:使用該操作符用于取得兩個結果集的交集
select ename,sal,job from emp where sal>2500 intersect select ename,sal,job from emp where job='manager';
minus:使用該操作符用于取得兩個結果集的差集,它只會顯示存在第一個集合中,而不存在第二個集合中的數據
select enmae,sal,job from emp where sal>2500 minus select ename,sal,job from emp where job='manager';
總結為集合運算就是將兩個或者多個結果集組合成一個結果集。
intersect ?交集 返回兩個查詢共有的記錄
union all ?并集 返回各個查詢的所有記錄,包括重復的記錄
union ? ? ?交集 返回各個查詢的所有記錄,不包括重復的記錄
MINUS ? 補集 返回第一個查詢檢查出的記錄減去第二個查詢檢索出來的記錄之后剩余的記錄
注意:當使用集合操作的時候,查詢所返回的列數以及列的類型必須匹配,列名可以不同。
附
(1)Distinct關鍵字
在Oracle中,可能出現若干相同的情況,那么可以用Distinct消除重復行
select distinct deptno from emp;
(2)多表查詢與單行子查詢可以實現相同的功能
查詢出銷售部(sales)下面的員工姓名,工作,工資
使用多表連接查詢的方法:
select dname,ename,job,sal from emp,dept where emp.deptno=dept.deptno and dname='SALES';
使用單行子查詢:
select ename,job,sal from emp where deptno=(select deptno from dept where dname='SALES');
(3)顯示高于自己部門平均工資的員工信息
分析:
1.找到所有部門的平均工資
select deptno,avg(sal) from emp group by deptno;
2.找到所有人的工資信息
select ename,sal,deptno from emp;
3.把兩個結果集使用多表連接組合組合起來
select * from emp,(select deptno,avg(sal) avgsal from emp group by deptno) damao where emp.deptno=damao.deptno;
4.去掉低于平均工資的那些數據即可:
select * from emp,(select deptno,avg(sal) avgsal from emp group by deptno) damao where emp.deptno=damao.deptno and sal>avgsal;
(4)emp表介紹
字段? ? ? ? ? ? ? 類型? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 描述
empno ? ? ? ? ?NUMBER(4) ? ? ? ? ? ? ? ? 表示雇員編號,是唯一編號
ename ? ? ? ? ?VAECHAR2(10) ? ? ? ? ? 表示雇員姓名
job ? ? ? ? ? ? ? ?VARCHAR2(9) ? ? ? ? ? ? 表示工作職位
mgr ? ? ? ? ? ? ?NUMBER(4) ? ? ? ? ? ? ? ? 表示一個雇員的領導編號
hiredate ? ? ? DATE ? ? ? ? ? ? ? ? ? ? ? ? ? ?表示雇傭日期
sal ? ? ? ? ? ? ? NUMBER(7,2) ? ? ? ? ? ? ? 表示月薪,工資
comm ? ? ? ? ?NUMBER(7,2) ? ? ? ? ? ? ? 表示獎金,或者稱為傭金
deptno ? ? ? ? NUMBER(2) ? ? ? ? ? ? ? ? 部門編號