查詢語句中select from where group by having order by limit的執(zhí)行順序
1.查詢中用到的關鍵詞主要包含六個,并且他們的順序依次為
select--from--where--group by--having--order by--limit
其中select和from是必須的谅摄,其他關鍵詞是可選的系馆,這六個關鍵詞的執(zhí)行順序
與sql語句的書寫順序并不是一樣的由蘑,而是按照下面的順序來執(zhí)行
from--where--group by--having--select--order by,
from:需要從哪個數(shù)據(jù)表檢索數(shù)據(jù)
where:過濾表中數(shù)據(jù)的條件
group by:如何將上面過濾出的數(shù)據(jù)分組
having:對上面已經(jīng)分組的數(shù)據(jù)進行過濾的條件
select:查看結(jié)果集中的哪個列,或列的計算結(jié)果
order by :按照什么樣的順序來查看返回的數(shù)據(jù)
limit :截取出目標頁數(shù)據(jù)
2.from后面的表關聯(lián)爷狈,是自右向左解析的
而where條件的解析順序是自下而上的裳擎。
也就是說,在寫SQL文的時候土辩,盡量把數(shù)據(jù)量大的表放在最右邊來進行關聯(lián),
而把能篩選出大量數(shù)據(jù)的條件放在where語句的最下面各墨。
SQL Select語句完整的執(zhí)行順序【從DBMS使用者角度】:
1启涯、from子句組裝來自不同數(shù)據(jù)源的數(shù)據(jù);
2黎做、where子句基于指定的條件對記錄行進行篩選松忍;
3鸣峭、group by子句將數(shù)據(jù)劃分為多個分組;
4爬骤、使用聚集函數(shù)進行計算莫换;
5、使用having子句篩選分組坷剧;
6喊暖、計算所有的表達式;
7、使用order by對結(jié)果集進行排序风范。
8、使用limit 截取目標頁數(shù)據(jù)
SQL Select語句的執(zhí)行步驟【從DBMS實現(xiàn)者角度锌半,這個對我們用戶意義不大】:
1)語法分析刊殉,分析語句的語法是否符合規(guī)范,衡量語句中各表達式的意義记焊。
2) 語義分析遍膜,檢查語句中涉及的所有數(shù)據(jù)庫對象是否存在,且用戶有相應的權限恩尾。
3)視圖轉(zhuǎn)換挽懦,將涉及視圖的查詢語句轉(zhuǎn)換為相應的對基表查詢語句。
4)表達式轉(zhuǎn)換冀偶, 將復雜的 SQL 表達式轉(zhuǎn)換為較簡單的等效連接表達式。
5)選擇優(yōu)化器角塑,不同的優(yōu)化器一般產(chǎn)生不同的“執(zhí)行計劃”
6)選擇連接方式蔫磨, ORACLE 有三種連接方式,對多表連接 ORACLE 可選擇適當?shù)倪B接方式圃伶。
7)選擇連接順序堤如, 對多表連接 ORACLE 選擇哪一對表先連接,選擇這兩表中哪個表做為源數(shù)據(jù)表窒朋。
8)選擇數(shù)據(jù)的搜索路徑搀罢,根據(jù)以上條件選擇合適的數(shù)據(jù)搜索路徑,如是選用全表搜索還是利用索引或是其他的方式侥猩。
9)運行“執(zhí)行計劃”榔至。
from 子句--執(zhí)行順序為從后往前、從右到左
表名(最后面的那個表名為驅(qū)動表唧取,執(zhí)行順序為從后往前, 所以數(shù)據(jù)量較少的表盡量放后)
oracle 的解析器按照從右到左的順序處理,F(xiàn)ROM 子句中的表名划提,F(xiàn)ROM 子句中寫在最后的表(基礎表 driving table)將被最先處理枫弟,即最后的表為驅(qū)動表,在FROM 子句中包含多個表的情況下,你必須選擇記錄條數(shù)最少的表作為基礎表鹏往。如果有3 個以上的表連接查詢, 那就需要選擇交叉表(intersection table)作為基礎表, 交叉表是指被其他表所引用的表
多表連接時淡诗,使用表的別名并把別名前綴于每個Column上。可以減少解析的時間并減少那些由Column 歧義引起的語法錯誤.
▼
▼
where子句--執(zhí)行順序為自下而上韩容、從右到左
ORACLE 采用自下而上從右到左的順序解析Where 子句,根據(jù)這個原理,表之間的連接必須寫在其他Where 條件之前,?可以過濾掉最大數(shù)量記錄的條件必須寫在Where 子句的末尾款违。
▼
▼
group by--執(zhí)行順序從左往右分組
提高GROUP BY 語句的效率, 可以通過將不需要的記錄在GROUP BY 之前過濾掉。即在GROUP BY前使用WHERE來過慮群凶,而盡量避免GROUP BY后再HAVING過濾插爹。
▼
▼
having 子句----很耗資源,盡量少用
避免使用HAVING 子句,?HAVING 只會在檢索出所有記錄之后才對結(jié)果集進行過濾. 這個處理需要排序,總計等操作.
如果能通過Where 子句在GROUP BY前限制記錄的數(shù)目,那就能減少這方面的開銷.
(非oracle 中)on座掘、where递惋、having 這三個都可以加條件的子句中,on 是最先執(zhí)行溢陪,where 次之萍虽,having 最后,因為on 是先把不符合條件的記錄過濾后才進行統(tǒng)計形真,它就可以減少中間運算要處理的數(shù)據(jù)杉编,按理說應該速度是最快的,
where 也應該比having 快點的咆霜,因為它過濾數(shù)據(jù)后才進行sum邓馒,在兩個表聯(lián)接時才用on 的,所以在一個表的時候蛾坯,就剩下where 跟having比較了光酣。
在這單表查詢統(tǒng)計的情況下,如果要過濾的條件沒有涉及到要計算字段脉课,那它們的結(jié)果是一樣的救军,只是where 可以使用rushmore 技術,而having 就不能倘零,在速度上后者要慢唱遭。
如果要涉及到計算的字段,就表示在沒計算之前呈驶,這個字段的值是不確定的拷泽,where 的作用時間是在計算之前就完成的,而having 就是在計算后才起作用的袖瞻,所以在這種情況下司致,兩者的結(jié)果會不同。
在多表聯(lián)接查詢時聋迎,on 比where 更早起作用脂矫。系統(tǒng)首先根據(jù)各個表之間的聯(lián)接條件,把多個表合成一個臨時表后砌庄,再由where 進行過濾羹唠,然后再計算,計算完后再由having 進行過濾娄昆。
由此可見佩微,要想過濾條件起到正確的作用,首先要明白這個條件應該在什么時候起作用萌焰,然后再決定放在那里哺眯。
▼
▼
select子句--少用*號,盡量取字段名稱扒俯。
ORACLE 在解析的過程中, 會將依次轉(zhuǎn)換成所有的列名, 這個工作是通過查詢數(shù)據(jù)字典完成的, 使用列名意味著將減少消耗時間奶卓。
sql 語句用大寫的;因為 oracle 總是先解析 sql 語句撼玄,把小寫的字母轉(zhuǎn)換成大寫的再執(zhí)行
▼
▼
order by子句--執(zhí)行順序為從左到右排序,很耗資源
補充:
今天遇到一個問題就是mysql中insert into 和update以及delete語句中能使用as別名嗎夺姑?目前還在查看,但是在查閱資料時發(fā)現(xiàn)了一些有益的知識掌猛,給大家分享一下盏浙,就是關于sql以及MySQL語句執(zhí)行順序:
sql和mysql執(zhí)行順序,發(fā)現(xiàn)內(nèi)部機制是一樣的荔茬。最大區(qū)別是在別名的引用上废膘。
一、sql執(zhí)行順序
(1)from
(3) join
(2) on
(4) where
(5)group by(開始使用select中的別名慕蔚,后面的語句中都可以使用)
(6) avg,sum....
(7)having
(8) select
(9) distinct
(10) order by
從這個順序中我們不難發(fā)現(xiàn)丐黄,所有的 查詢語句都是從from開始執(zhí)行的,在執(zhí)行過程中孔飒,每個步驟都會為下一個步驟生成一個虛擬表灌闺,這個虛擬表將作為下一個執(zhí)行步驟的輸入。
第一步:首先對from子句中的前兩個表執(zhí)行一個笛卡爾乘積十偶,此時生成虛擬表 vt1(選擇相對小的表做基礎表)
第二步:接下來便是應用on篩選器菩鲜,on 中的邏輯表達式將應用到 vt1 中的各個行,篩選出滿足on邏輯表達式的行惦积,生成虛擬表 vt2
第三步:如果是outer join 那么這一步就將添加外部行接校,left outer jion 就把左表在第二步中過濾的添加進來,如果是right outer join 那么就將右表在第二步中過濾掉的行添加進來狮崩,這樣生成虛擬表 vt3
第四步:如果 from 子句中的表數(shù)目多余兩個表蛛勉,那么就將vt3和第三個表連接從而計算笛卡爾乘積,生成虛擬表睦柴,該過程就是一個重復1-3的步驟诽凌,最終得到一個新的虛擬表 vt3。
第五步:應用where篩選器坦敌,對上一步生產(chǎn)的虛擬表引用where篩選器侣诵,生成虛擬表vt4痢法,在這有個比較重要的細節(jié)不得不說一下,對于包含outer join子句的查詢杜顺,就有一個讓人感到困惑的問題财搁,到底在on篩選器還是用where篩選器指定邏輯表達式呢?on和where的最大區(qū)別在于躬络,如果在on應用邏輯表達式那么在第三步outer join中還可以把移除的行再次添加回來尖奔,而where的移除的最終的。舉個簡單的例子穷当,有一個學生表(班級,姓名)和一個成績表(姓名,成績)提茁,我現(xiàn)在需要返回一個x班級的全體同學的成績,但是這個班級有幾個學生缺考馁菜,也就是說在成績表中沒有記錄茴扁。為了得到我們預期的結(jié)果我們就需要在on子句指定學生和成績表的關系(學生.姓名=成績.姓名)那么我們是否發(fā)現(xiàn)在執(zhí)行第二步的時候,對于沒有參加考試的學生記錄就不會出現(xiàn)在vt2中汪疮,因為他們被on的邏輯表達式過濾掉了,但是我們用left outer join就可以把左表(學生)中沒有參加考試的學生找回來丹弱,因為我們想返回的是x班級的所有學生,如果在on中應用學生.班級='x'的話铲咨,left outer join會把x班級的所有學生記錄找回(感謝網(wǎng)友康欽謀__康欽苗的指正)躲胳,所以只能在where篩選器中應用學生.班級='x' 因為它的過濾是最終的。
第六步:group by 子句將中的唯一的值組合成為一組纤勒,得到虛擬表vt5坯苹。如果應用了group by,那么后面的所有步驟都只能得到的vt5的列或者是聚合函數(shù)(count摇天、sum粹湃、avg等)。原因在于最終的結(jié)果集中只為每個組包含一行泉坐。這一點請牢記为鳄。
第七步:應用cube或者rollup選項,為vt5生成超組腕让,生成vt6.
第八步:應用having篩選器孤钦,生成vt7。having篩選器是第一個也是為唯一一個應用到已分組數(shù)據(jù)的篩選器纯丸。
第九步:處理select子句偏形。將vt7中的在select中出現(xiàn)的列篩選出來。生成vt8.
第十步:應用distinct子句觉鼻,vt8中移除相同的行俊扭,生成vt9。事實上如果應用了group by子句那么distinct是多余的坠陈,原因同樣在于萨惑,分組的時候是將列中唯一的值分成一組捐康,同時只為每一組返回一行記錄,那么所以的記錄都將是不相同的庸蔼。
第十一步:應用order by子句吹由。按照order_by_condition排序vt9,此時返回的一個游標朱嘴,而不是虛擬表。sql是基于集合的理論的粗合,集合不會預先對他的行排序萍嬉,它只是成員的邏輯集合,成員的順序是無關緊要的隙疚。對表進行排序的查詢可以返回一個對象壤追,這個對象包含特定的物理順序的邏輯組織。這個對象就叫游標供屉。正因為返回值是游標行冰,那么使用order by 子句查詢不能應用于表表達式。排序是很需要成本的伶丐,除非你必須要排序悼做,否則最好不要指定order by,最后哗魂,在這一步中是第一個也是唯一一個可以使用select列表中別名的步驟肛走。
第十二步:應用top選項。此時才返回結(jié)果給請求者即用戶录别。
二朽色、mysql的執(zhí)行順序
SELECT語句定義
一個完成的SELECT語句包含可選的幾個子句。SELECT語句的定義如下:
SQL代碼
[java]?view plaincopy
?[]?[]?[]?[]?[]?[]
SELECT子句是必選的组题,其它子句如WHERE子句葫男、GROUP BY子句等是可選的。
一個SELECT語句中崔列,子句的順序是固定的梢褐。例如GROUP BY子句不會位于WHERE子句的前面。
SELECT語句執(zhí)行順序
SELECT語句中子句的執(zhí)行順序與SELECT語句中子句的輸入順序是不一樣的赵讯,所以并不是從SELECT子句開始執(zhí)行的利职,而是按照下面的順序執(zhí)行:
開始->FROM子句->WHERE子句->GROUP BY子句->HAVING子句->ORDER BY子句->SELECT子句->LIMIT子句->最終結(jié)果
每個子句執(zhí)行后都會產(chǎn)生一個中間結(jié)果,供接下來的子句使用瘦癌,如果不存在某個子句猪贪,就跳過
對比了一下,mysql和sql執(zhí)行順序基本是一樣的, 標準順序的 SQL 語句為:
[html]?view plaincopy
select?考生姓名,?max(總成績)?as?max總成績
from?tb_Grade
where?考生姓名?is?not?null
group?by?考生姓名
having?max(總成績)>600
order?by?max總成績
在上面的示例中 SQL 語句的執(zhí)行順序如下:
(1). 首先執(zhí)行 FROM 子句, 從 tb_Grade 表組裝數(shù)據(jù)源的數(shù)據(jù)
(2). 執(zhí)行 WHERE 子句, 篩選 tb_Grade 表中所有數(shù)據(jù)不為 NULL 的數(shù)據(jù)
(3). 執(zhí)行 GROUP BY 子句, 把 tb_Grade 表按 "學生姓名" 列進行分組(注:這一步開始才可以使用select中的別名讯私,他返回的是一個游標热押,而不是一個表砾莱,所以在where中不可以使用select中的別名,而having卻可以使用棉饶,感謝網(wǎng)友zyt1369提出這個問題)
(4). 計算 max() 聚集函數(shù), 按 "總成績" 求出總成績中最大的一些數(shù)值
(5). 執(zhí)行 HAVING 子句, 篩選課程的總成績大于 600 分的.
(7). 執(zhí)行 ORDER BY 子句, 把最后的結(jié)果按 "Max 成績" 進行排序.