查詢基礎(chǔ)
算術(shù)運(yùn)算符
(+)(-)(*)(/) 值得注意的是:/ 在oracle中就相當(dāng)于顯示中的除法 5/2 = 2.5
!=,^=,<> 不等于
<? 小于
>? 大于
<= 小于等于
>= 大于等于
邏輯操作符
or and not
字符串連接操作符(||)
在Oracle中,字符串的連接用雙豎線(||)表示。比如,在EMP表中,查詢工資在2000元以上的姓名以及工作。
SELECT (ENAME || 'is a ' || JOB) AS "Employee Details"? FROM EMP? WHERE SAL>2000;
代碼解析:
① Oracle中字符串可以用單引號(hào),也可以用雙引號(hào),在別名中存在空格時(shí),必須用雙引號(hào)。在表名、列名時(shí)用雙引號(hào)。
轉(zhuǎn)換字符串為日期 to_date
例:
select empno,ename,hiredate
from emp
where hiredate >to_date('1980/01/01','yyyy/mm/dd') and hiredate;
聚合函數(shù)/分組函數(shù)
(聚合函數(shù)和分組函數(shù)都是描述的同一個(gè)概念,就是多行查詢結(jié)果 聚合計(jì)算成一個(gè)結(jié)果返回,是查到多行返回一個(gè)結(jié)果,所以就涉及到按某個(gè)列進(jìn)行分組的問(wèn)題。)
聚合函數(shù)(distinct 對(duì)不同的值進(jìn)行操作 /all 對(duì)所有值進(jìn)行操作 )
avg 平均
select avg(sal) from emp;
select avg(distinct sal) from emp;
max 最大
select max(sal) from emp;
select max(distinct sal) from emp;
min 最小
select min(sal) from emp;
select min(distinct sal) from emp;
stddev 標(biāo)準(zhǔn)差
select stddev(sal) from emp;
select stddev(distinct sal) from emp;
variance 協(xié)方差
select variance(sal) from emp;
select variance(distinct sal) from emp;
sum 求和
select sum(sal) from emp;
select sum(distinct sal) from emp;
count 記錄個(gè)數(shù)
select count(sal) from emp;
select count(distinct sal) from emp;
median 中值 沒有 distinct 加持
nvl 空值處理函數(shù)
select id,nvl(name,'無(wú)名') name from test;
分組統(tǒng)計(jì)
select 列名 [as 別名],[聚合函數(shù)]
from 表名
where 查詢條件表達(dá)式
group by 分組列名
having 分組查詢表達(dá)式
order by 排序的列名[asc 升序 desc 降序] 默認(rèn)是升序
例:
select CategoryName, count(*), AVG(Rating)
from BOOKSHELF
where Rating>1
group by CategoryName
having CategoryName like 'A%'
order by count(*) desc
分析:
1.基于where Rating>1 篩選出符合條件的行;
2.基于group by CategoryName 對(duì)篩選的結(jié)果進(jìn)行分組;
3.為每個(gè) CategoryName組計(jì)算count(*)
4.基于having CategoryName like 'A%' 留下符合條件的組
5.根據(jù)order by 的條件對(duì)剩下的行組進(jìn)行排序,SQL中的count(*)也是分組函數(shù)
注意事項(xiàng):
1.分組函數(shù)(max、min、avg、count、sum)只能出現(xiàn)在選擇列表、having子句、order by子句中,不能出現(xiàn)在where子句和group by子句中
select empno, initcap(ename), avg(sal) from emp;--非法 不允許在 WHERE 子句中使用分組函數(shù)
2.如果在select語(yǔ)句中同時(shí)包含有g(shù)roup by,having,order by,順序先group by,having,order by
select 列名1,.. From 表名 Where 條件 group by 分組列名 having 分組過(guò)濾 order by 排序列名
3.如果選擇列表同時(shí)包含列、表達(dá)式和分組函數(shù),則這些列、表達(dá)式都必須出現(xiàn)在group by中
select deptno,avg(sal),max(sal) from emp group by deptno having avg(sal)<2000 這里deptno 就必須出現(xiàn)在group by中
group by 詳解
Group by子句:
●? Group by子句將一個(gè)表分成許多小組,并對(duì)每一個(gè)小組返回一個(gè)計(jì)算值。
●? Group by expression:指按什么列進(jìn)行分組
注意事項(xiàng):
●? 在select子句中,如果使用了分組函數(shù),就不能對(duì)group by指定的列使用分組函數(shù)。
●? 使用where子句可以預(yù)先排除某些記錄
●? 在Group by子句中必須有表中的列
●? Group by子句不能使用別名
●? 可以通過(guò)Order by子句改變它的排序情況
基本用法
對(duì)于其基本的用法直接以實(shí)例的形式來(lái)展示。
1、統(tǒng)計(jì)各個(gè)部門的員工的工資的總和
[sql]
select deptno ,sum(sal) from emp group by deptno;
--升序排列
select deptno ,sum(sal) from emp group by deptno order by deptno asc;
2、統(tǒng)計(jì)各個(gè)部門各個(gè)職業(yè)的員工的工資的總和
[sql]
select deptno,job,sum(sal) from emp
group by(deptno,job) order by deptno;
Tips:第二個(gè)實(shí)例其實(shí)就是多列分組,先對(duì)部門進(jìn)行分組,之后對(duì)職位進(jìn)行分組。
DEPTNO JOB? ? ? ? SUM(SAL)
------ --------- ----------
10 CLERK? ? ? ? 2173.25
10 MANAGER? ? ? ? 2450
10 PRESIDENT? ? ? 6000
20 ANALYST? ? ? ? 6000
20 CLERK? ? ? ? ? 1900
20 MANAGER? ? ? ? 2975
30 CLERK? ? ? ? ? ? 950
30 MANAGER? ? ? ? 2850
30 SALESMAN? ? ? ? 5600
3、Having子句的使用
我們知道分組函數(shù)是不能卸載WHERE子句中的,但是有時(shí)候我們需要對(duì)分組進(jìn)行限定
只有符合某個(gè)要求的分組才會(huì)被選擇出來(lái),那么就可以通過(guò)having子句來(lái)進(jìn)行。具體的用法
同樣以一個(gè)實(shí)例說(shuō)明。
在2的基礎(chǔ)上添加一個(gè)條件:工資總和必須在10000以上
[sql]
select deptno ,sum(sal) from emp group by deptno
having sum(sal)>10000;
DEPTNO? SUM(SAL)
------ ----------
20? ? ? 10875
10? 10623.25
Tips:思考一下Having子句與where子句的區(qū)別
兩者都是對(duì)數(shù)據(jù)進(jìn)行篩選,不同的是where是對(duì)原數(shù)據(jù)進(jìn)行篩選而having則是對(duì)匯總后的結(jié)果進(jìn)行一個(gè)篩選而已!
擴(kuò)展用法
除了基本的用法外,group by還具有一些擴(kuò)展的用法,不過(guò)大多數(shù)情況下基本的用法基本上
就可以滿足我們的操作了。
1、使用rollup操作符
rollup,是group by子句的一種擴(kuò)展,可以為每個(gè)分組返回小計(jì)記錄以及對(duì)所有的分組返回
總計(jì)記錄。下面看看其基本的用法吧。
⊙? 向rollup傳遞一列
[sql]
select deptno,sum(sal) from emp where DEPTNO>=20 group by rollup(deptno) ;
DEPTNO? SUM(SAL)
------ ----------
20? ? ? 10875
30? ? ? 9400
20275 -對(duì)返回值進(jìn)行一個(gè)總計(jì)
不過(guò)需要注意的是要對(duì)所有的記錄進(jìn)行一個(gè)總計(jì)的話,應(yīng)該要一個(gè)聚合函數(shù)
不然根本沒有實(shí)際的意義!
⊙? 向rollup傳遞多列
Tips:需要注意的是rollup作用于多列的時(shí)候,之對(duì)第一列起作用!
[sql]
select deptno,job,sum(sal) from emp group by rollup(deptno,job);
select deptno,job,sum(sal) from emp group by rollup(job,deptno);
DEPTNO JOB? ? ? ? SUM(SAL)
------ --------- ----------
10 CLERK? ? ? ? 2173.25
20 CLERK? ? ? ? ? 1900
30 CLERK? ? ? ? ? ? 950
CLERK? ? ? ? 5023.25
20 ANALYST? ? ? ? 6000
ANALYST? ? ? ? 6000
10 MANAGER? ? ? ? 2450
20 MANAGER? ? ? ? 2975
30 MANAGER? ? ? ? 2850
MANAGER? ? ? ? 8275
30 SALESMAN? ? ? ? 5600
SALESMAN? ? ? ? 5600
10 PRESIDENT? ? ? 6000
PRESIDENT? ? ? 6000
30898.25
可以看出的是除了最后又一個(gè)總計(jì)外,每個(gè)deptno都有一個(gè)小計(jì),至于兩個(gè)
列交換的結(jié)果原理是一樣的,這里就不在演示了。
2、使用cube操作符
cube也是Group by子句的一種擴(kuò)展,返回每一個(gè)列組合的小計(jì)記錄,同時(shí)在頭部加上
總計(jì)記錄。(Oracle 11g)貌似和以前不一樣?
⊙? 向cube傳遞一列
[sql]
select deptno,sum(sal) from emp group by cube(deptno);
DEPTNO? SUM(SAL)
------ ----------
30898.25
10? 10623.25
20? ? ? 10875
30? ? ? 9400
效果看起來(lái)和rollup沒有什么兩樣嘛,只是總計(jì)的位置變了嘛,別慌看多列的情況!
⊙? 向cube傳遞多列
[sql]
select deptno,job,sum(sal) from emp group by cube(deptno,job);
DEPTNO JOB? ? ? ? SUM(SAL)
------ --------- ----------
30898.25
CLERK? ? ? ? 5023.25
ANALYST? ? ? ? 6000
MANAGER? ? ? ? 8275
SALESMAN? ? ? ? 5600
PRESIDENT? ? ? 6000
10? ? ? ? ? ? 10623.25
10 CLERK? ? ? ? 2173.25
10 MANAGER? ? ? ? 2450
10 PRESIDENT? ? ? 6000
20? ? ? ? ? ? ? ? 10875
20 CLERK? ? ? ? ? 1900
20 ANALYST? ? ? ? 6000
20 MANAGER? ? ? ? 2975
30? ? ? ? ? ? ? ? 9400
30 CLERK? ? ? ? ? ? 950
30 MANAGER? ? ? ? 2850
30 SALESMAN? ? ? ? 5600
可以看出cube在每一個(gè)deptno都返回一個(gè)記錄(部門的所有工資總數(shù)),并且就部門中的? 每種工作的工資總數(shù)做了一個(gè)小計(jì),而且就每種工作的工資做了一個(gè)小計(jì)(沒有部門限制),而且對(duì)所有的工資總數(shù)做了一個(gè)總計(jì)。
cube和rollup的區(qū)別小結(jié):
通過(guò)上面的學(xué)習(xí),我們可能有一種感覺,那就是直觀上cube和rollup的組合情況不一樣,
可以從這方面去區(qū)分,但是最好別從這方面思考問(wèn)題。
ROLLUP (a,b,c...n)
group by (a,b,c)->(a,b)->(a)->全表group by? 共分組n+1次
CUBE(a,b,c...n)
group by(a,b,c)->(a,b)->(a,c)->(a)->(b,c)-(b)-(c)->全表group by? 共分組2n次方
至于其他的擴(kuò)展用法,就先不展示了,之后會(huì)遇到的!Over!
模糊查詢
like
在Where子句中,可以對(duì)datetime、char、varchar字段類型的列用Like子句配合通配符選取那些“很像...”的數(shù)據(jù)記錄
通配符
%? 零或者多個(gè)字符
_? 單一任何字符(下劃線)
/? 特殊字符
[]? 在某一范圍內(nèi)的字符,如[0-9]或者[aeth]
[^] 不在某范圍內(nèi)的字符,如[^0-9]或者[^aeth]
1.%:表示任意0個(gè)或多個(gè)字符。可匹配任意類型和長(zhǎng)度的字符,有些情況下若是中文,請(qǐng)使用兩個(gè)百分號(hào)(%%)表示。
比如 SELECT * FROM [user] WHERE u_name LIKE '%三%'
將會(huì)把u_name為“張三”,“張貓三”、“三腳貓”,“唐三藏”等等有“三”的記錄全找出來(lái)。
另外,如果需要找出u_name中既有“三”又有“貓”的記錄,請(qǐng)使用and條件
SELECT * FROM [user] WHERE u_name LIKE '%三%' AND u_name LIKE '%貓%'
若使用 SELECT * FROM [user] WHERE u_name LIKE '%三%貓%'
雖然能搜索出“三腳貓”,但不能搜索出符合條件的“張貓三”。
2._: 表示任意單個(gè)字符。匹配單個(gè)任意字符,它常用來(lái)限制表達(dá)式的字符長(zhǎng)度語(yǔ)句:
比如 SELECT * FROM [user] WHERE u_name LIKE '_三_'
只找出“唐三藏”這樣u_name為三個(gè)字且中間一個(gè)字是“三”的;
再比如 SELECT * FROM [user] WHERE u_name LIKE '三__';
只找出“三腳貓”這樣name為三個(gè)字且第一個(gè)字是“三”的;
3.[ ]:表示括號(hào)內(nèi)所列字符中的一個(gè)(類似正則表達(dá)式)。指定一個(gè)字符、字符串或范圍,要求所匹配對(duì)象為它們中的任一個(gè)。
比如 SELECT * FROM [user] WHERE u_name LIKE '[張李王]三'
將找出“張三”、“李三”、“王三”(而不是“張李王三”);
如 [ ] 內(nèi)有一系列字符(01234、abcde之類的)則可略寫為“0-4”、“a-e”
SELECT * FROM [user] WHERE u_name LIKE '老[1-9]'
將找出“老1”、“老2”、……、“老9”;
4.[^ ] :表示不在括號(hào)所列之內(nèi)的單個(gè)字符。其取值和 [] 相同,但它要求所匹配對(duì)象為指定字符以外的任一個(gè)字符。
比如 SELECT * FROM [user] WHERE u_name LIKE '[^張李王]三'
將找出不姓“張”、“李”、“王”的“趙三”、“孫三”等;
SELECT * FROM [user] WHERE u_name LIKE '老[^1-4]';
將排除“老1”到“老4”,尋找“老5”、“老6”、……
5.查詢內(nèi)容包含通配符時(shí)
由于通配符的緣故,導(dǎo)致我們查詢特殊字符“%”、“_”、“[”的語(yǔ)句無(wú)法正常實(shí)現(xiàn),而把特殊字符用“[ ]”括起便可正常查詢。據(jù)此我們寫出以下函數(shù):
function sqlencode(str)
str=replace(str,"[","[[]") '此句一定要在最前
str=replace(str,"_","[_]")
str=replace(str,"%","[%]")
sqlencode=str
end function
空值查詢
SELECT ename As 姓名,comm AS? 獎(jiǎng)金 FROM emp WHERE comm IS NULL
between and 條件
SELECT *? FROM teacher
WHERE birthday? between '1968/1/1'? and? '1970/1/1'
in運(yùn)算符用法:把某一字段中內(nèi)容與所列出的查詢內(nèi)容列表匹配的記錄查詢出來(lái)
集合運(yùn)算:就是將兩個(gè)或者多個(gè)結(jié)果集組合成為一個(gè)結(jié)果集。
INTERSECT(交集),返回兩個(gè)查詢共有的記錄
UNION ALL(并集),返回各個(gè)查詢的所有記錄,包括重復(fù)的記錄
UNION(并集),返回各個(gè)查詢的所有記錄,不包括重復(fù)的記錄
MINUS(補(bǔ)集),返回第一個(gè)查詢檢索出的記錄減去第二個(gè)查詢檢索出的記錄之后剩余的記錄。
例:
SELECT deptno FROM? dept
MINUS
SELECT deptno FROM emp;
多表連接
inner join / join 內(nèi)連接 on 條件
自然連接
natural join
自然連接是在兩張表中尋找那些數(shù)據(jù)類型和列名都相同的字段,然后自動(dòng)地將他們連接起來(lái),并返回所有符合條件按的結(jié)果。(還會(huì)去相等行)
外連接
outer join(左外連接left outer join/ left join--左邊為主表,右外連接right outer join/ right join--右邊為主表,全外連接)
outer join則會(huì)返回每個(gè)滿足第一個(gè)(頂端)輸入與第二個(gè)(底端)輸入的聯(lián)接的行。它還返回任何在第二個(gè)輸入中沒有匹配行的第一個(gè)輸入中的行。外連接分為三種: 左外連接,右外連接,全外連接。 對(duì)應(yīng)SQL:LEFT/RIGHT/FULL OUTER JOIN。 通常我們省略outer 這個(gè)關(guān)鍵字。 寫成:LEFT/RIGHT/FULL JOIN。
左右鏈接
在左外連接和右外連接時(shí)都會(huì)以一張表為基表,該表的內(nèi)容會(huì)全部顯示,然后加上兩張表匹配的內(nèi)容。 如果基表的數(shù)據(jù)在另一張表沒有記錄。 那么在相關(guān)聯(lián)的結(jié)果集行中列顯示為空值(NULL)。
用(+)來(lái)實(shí)現(xiàn), 這個(gè)+號(hào)可以這樣來(lái)理解: + 表示補(bǔ)充,即哪個(gè)表有加號(hào),這個(gè)表就是匹配表。另一個(gè)就是主表;
select * from dave a right join bl b on a.id = b.id;
select * from dave a,bl b where a.id(+)=b.id;
2. ? ? ? ? ID NAME? ? ? ? ? ? ? ID NAME
3. ---------- ---------- ---------- ----------
4. ? ? ? ? 1 dave? ? ? ? ? ? ? ? 1 dave
5. ? ? ? ? 2 bl? ? ? ? ? ? ? ? ? 2 bl
6. ? ? ? ? 1 bl? ? ? ? ? ? ? ? ? 1 dave
7. ? ? ? ? 2 dave? ? ? ? ? ? ? ? 2 bl
8. ? ? ? ? 3 dba? ? ? ? ? ? ? ? 3 big bird
9. ? ? ? ? 4 sf-express? ? ? ? ? 4 exc
10. ? ? ? ? ? ? ? ? ? ? ? ? ? 9 懷寧
全外鏈接 full outer join/ full join
左表和右表都不做限制,所有的記錄都顯示,兩表不足的地方用null 填充。 全外連接不支持(+)這種寫法。
自連接
自連接(self join)是SQL語(yǔ)句中經(jīng)常要用的連接方式,使用自連接可以將自身表的一個(gè)鏡像當(dāng)作另一個(gè)表來(lái)對(duì)待,從而能夠得到一些特殊的數(shù)據(jù)。
每一個(gè)員工自己的名字和經(jīng)理的名字都找出來(lái)
select work.ename worker,mgr.ename manger
from emp work,emp mgr
where work.mgr = mgr.empno(+)
order by work.ename;
子查詢
子查詢是指子查詢?cè)谥鞑樵兦皥?zhí)行一次,主查詢使用子查詢的結(jié)果
注意事項(xiàng):
在查詢時(shí)基于未知時(shí)應(yīng)考慮使用子查詢
子查詢必須包含在括號(hào)內(nèi)
將子查詢放在比較運(yùn)算符的右側(cè),以增強(qiáng)可讀性.
除非進(jìn)行Top-N分析,否則不要再子查詢中使用Order by子句
對(duì)單行子查詢使用單行運(yùn)算符
對(duì)多行子查詢使用多行運(yùn)算符
單行子查詢
單行子查詢
單行子查詢只返回一行記錄
對(duì)單行子查詢可使用單行記錄比較運(yùn)算符
=-----------------等于
>-----------------大于
>=----------------大于等于
<-----------------小于
<=----------------小于等于
<>----------------不等于
select * from emp
where sal>(select sal
from emp where empno=7000);
子查詢空值/多值問(wèn)題
如果子查詢未返回任何行,則主查詢頁(yè)不會(huì)返回任何結(jié)果
如果子查詢返回單行結(jié)果,則為單行子查詢,可以在主查詢中對(duì)其使用相應(yīng)的單行記錄比較運(yùn)算符
如果子查詢返回多行結(jié)果,則為多行子查詢,此時(shí)不允許對(duì)其使用單行記錄比較運(yùn)算符
多行子查詢
多行子查詢返回多行記錄
對(duì)多行子查詢只能使用多行記錄比較運(yùn)算符
in---------------等于列表中的任何一個(gè)
any--------------和子查詢返回的任意一個(gè)值比較
all--------------和子查詢返回的所有值比較
some-------------即一些。和any的用法基本相同。用any的地方都可以用some代替。不過(guò)some大多用在=操作中。表示等于所選集合中的任何一個(gè)。當(dāng)然any也可以用于=操作中,效果和some相同
select * from emp
where sal>any(select avg(sal) from emp group by deptno);
select * from emp
where sal>all(select avg(sal) from emp group by deptno);
select * from emp
where job in(select job from emp where ename='martin' or ename='ssss');
select * from emp t
where t.sal=some(select sal from hhgy.emp where deptno=30);
TopN查詢r(jià)ownum高級(jí)查詢
查詢出3行到7行的員工名
select *
from (select ename,rownum rn from emp )
where rn > 3 and rn < 7;