[SQL]sql的執(zhí)行順序詳解

結合上圖标沪,整理出如下偽SQL查詢語句



從這個順序中我們可以發(fā)現(xiàn),所有的查詢語句都是從?FROM?開始執(zhí)行的军浆。在實際執(zhí)行過程中,每個步驟都會為下一個步驟生成一個虛擬表申钩,這個虛擬表將作為下一個執(zhí)行步驟的輸入罗洗。 接下來,我們詳細的介紹下每個步驟的具體執(zhí)行過程馏鹤。


1 FROM?執(zhí)行笛卡爾積

FROM 才是 SQL 語句執(zhí)行的第一步勃救,并非 SELECT 瓢省。對FROM子句中的前兩個表執(zhí)行笛卡爾積(交叉聯(lián)接)废亭,生成虛擬表VT1,獲取不同數(shù)據(jù)源的數(shù)據(jù)集粗恢。

FROM子句執(zhí)行順序為從后往前佛掖、從右到左拴魄,F(xiàn)ROM 子句中寫在最后的表(基礎表 driving table)將被最先處理,即最后的表為驅動表跛溉,當FROM 子句中包含多個表的情況下,我們需要選擇數(shù)據(jù)最少的表作為基礎表。


2 ON 應用ON過濾器

對虛擬表VT1?應用ON篩選器落萎,ON 中的邏輯表達式將應用到虛擬表?VT1中的各個行瓷产,篩選出滿足ON 邏輯表達式的行,生成虛擬表?VT2?。


3 JOIN 添加外部行

如果指定了OUTER JOIN保留表中未找到匹配的行將作為外部行添加到虛擬表?VT2炎疆,生成虛擬表?VT3形入。保留表如下:

LEFT OUTER JOIN把左表記為保留表

RIGHT OUTER JOIN把右表記為保留表

FULL OUTER JOIN把左右表都作為保留表

在虛擬表?VT2表的基礎上添加保留表中被過濾條件過濾掉的數(shù)據(jù)全跨,非保留表中的數(shù)據(jù)被賦予NULL值,最后生成虛擬表?VT3亿遂。

如果FROM子句包含兩個以上的表,則對上一個聯(lián)接生成的結果表和下一個表重復執(zhí)行步驟1~3蛇数,直到處理完所有的表為止挪钓。


4 WHERE 應用WEHRE過濾器

對虛擬表?VT3應用WHERE篩選器。根據(jù)指定的條件對數(shù)據(jù)進行篩選苞慢,并把滿足的數(shù)據(jù)插入虛擬表?VT4诵原。

由于數(shù)據(jù)還沒有分組,因此現(xiàn)在還不能在WHERE過濾器中使用聚合函數(shù)對分組統(tǒng)計的過濾挽放。

同時绍赛,由于還沒有進行列的選取操作,因此在SELECT中使用列的別名也是不被允許的辑畦。

備注:

?應用where篩選器吗蚌,對上一步生產(chǎn)的虛擬表引用where篩選器,生成虛擬表vt4纯出,在這有個比較重要的細節(jié)不得不說一下蚯妇,對于包含outer join子句的查詢敷燎,就有一個讓人感到困惑的問題,到底在on篩選器還是用where篩選器指定邏輯表達式呢箩言?on和where的最大區(qū)別在于硬贯,如果在on應用邏輯表達式那么在第三步outer join中還可以把移除的行再次添加回來,而where的移除的最終的陨收。舉個簡單的例子饭豹,有一個學生表(班級,姓名)和一個成績表(姓名,成績),我現(xiàn)在需要返回一個x班級的全體同學的成績务漩,但是這個班級有幾個學生缺考拄衰,也就是說在成績表中沒有記錄。為了得到我們預期的結果我們就需要在on子句指定學生和成績表的關系(學生.姓名=成績.姓名)那么我們是否發(fā)現(xiàn)在執(zhí)行第二步的時候饵骨,對于沒有參加考試的學生記錄就不會出現(xiàn)在vt2中翘悉,因為他們被on的邏輯表達式過濾掉了,但是我們用left outer join就可以把左表(學生)中沒有參加考試的學生找回來,因為我們想返回的是x班級的所有學生居触,如果在on中應用學生.班級='x'的話诗越,left outer join會把x班級的所有學生記錄找回砖瞧,所以只能在where篩選器中應用學生.班級='x' 因為它的過濾是最終的。


5 GROUP BY 分組

按GROUP BY子句中的列/列表將虛擬表?VT4中的行唯一的值組合成為一組嚷狞,生成虛擬表VT5。如果應用了GROUP BY床未,那么后面的所有步驟都只能得到的虛擬表VT5的列或者是聚合函數(shù)(count竭翠、sum、avg等)薇搁。原因在于最終的結果集中只為每個組包含一行斋扰。

同時,從這一步開始啃洋,后面的語句中都可以使用SELECT中的別名传货。


6?AGG_FUNC?計算聚合函數(shù)

計算 max 等聚合函數(shù)。SQL Aggregate 函數(shù)計算從列中取得的值宏娄,返回一個單一的值问裕。常用的 Aggregate 函數(shù)包涵以下幾種:

AVG:返回平均值

COUNT:返回行數(shù)

FIRST:返回第一個記錄的值

LAST:返回最后一個記錄的值

MAX: 返回最大值

MIN:返回最小值

SUM: 返回總和


7 WITH 應用ROLLUP或CUBE

對虛擬表?VT5應用ROLLUP或CUBE選項,生成虛擬表?VT6孵坚。

CUBE 和 ROLLUP 區(qū)別如下:

CUBE 生成的結果數(shù)據(jù)集顯示了所選列中值的所有組合的聚合粮宛。

ROLLUP 生成的結果數(shù)據(jù)集顯示了所選列中值的某一層次結構的聚合窥淆。


8 HAVING 應用HAVING過濾器

對虛擬表VT6應用HAVING篩選器。根據(jù)指定的條件對數(shù)據(jù)進行篩選巍杈,并把滿足的數(shù)據(jù)插入虛擬表VT7忧饭。

HAVING?語句在SQL中的主要作用與WHERE語句作用是相同的,但是HAVING是過濾聚合值筷畦,在 SQL 中增加 HAVING 子句原因就是眷昆,WHERE 關鍵字無法與聚合函數(shù)一起使用,HAVING子句主要和GROUP BY子句配合使用汁咏。


9 SELECT 選出指定列

將虛擬表?VT7中的在SELECT中出現(xiàn)的列篩選出來亚斋,并對字段進行處理,計算SELECT子句中的表達式攘滩,產(chǎn)生虛擬表?VT8帅刊。


10 DISTINCT 行去重

將重復的行從虛擬表?VT8中移除,產(chǎn)生虛擬表?VT9漂问。DISTINCT用來刪除重復行赖瞒,只保留唯一的。

事實上如果應用了group by子句那么distinct是多余的蚤假,原因同樣在于栏饮,分組的時候是將列中唯一的值分成一組,同時只為每一組返回一行記錄磷仰,那么所有的記錄都將是不相同的袍嬉。


11 ORDER BY 排列

將虛擬表?VT9中的行按ORDER BY 子句中的列/列表排序,生成游標?VC10?灶平;此時返回的一個游標伺通,而不是虛擬表。sql是基于集合的理論的逢享,集合不會預先對他的行排序罐监,它只是成員的邏輯集合,成員的順序是無關緊要的瞒爬。對表進行排序的查詢可以返回一個對象弓柱,這個對象包含特定的物理順序的邏輯組織。這個對象就叫游標侧但。正因為返回值是游標矢空,那么使用order by 子句查詢不能應用于表表達式。排序是很需要成本的俊犯,除非你必須要排序妇多,否則最好不要指定order by,最后燕侠,在這一步中是第一個也是唯一一個可以使用select列表中別名的步驟者祖。


12 LIMIT/OFFSET 指定返回行

從VC10的開始處選擇指定數(shù)量行立莉,生成虛擬表?VT11,并返回調用者七问。


實例

接下來蜓耻,我們看一個實例,以下SQL查詢語句是否存在問題械巡?


首先刹淌,我們先看下如上SQL的執(zhí)行順序,如下:

首先執(zhí)行 FROM 子句, 從學生成績表中組裝數(shù)據(jù)源的數(shù)據(jù)讥耗。

執(zhí)行 WHERE 子句, 篩選學生成績表中所有學生的數(shù)學成績不為 NULL 的數(shù)據(jù) 有勾。

執(zhí)行 GROUP BY 子句, 把學生成績表按 "班級" 字段進行分組。

計算 avg 聚合函數(shù), 按找每個班級分組求出?數(shù)學平均成績古程。

執(zhí)行 HAVING 子句, 篩選出班級?數(shù)學平均成績大于 75 分的蔼卡。

執(zhí)行SELECT語句,返回數(shù)據(jù)挣磨,但別著急雇逞,還需要執(zhí)行后面幾個步驟。

執(zhí)行 ORDER BY 子句, 把最后的結果按 "數(shù)學平均成績" 進行排序茁裙。

執(zhí)行LIMIT 塘砸,限制僅返回3條數(shù)據(jù)。結合ORDER BY 子句晤锥,即返回所有班級中數(shù)學平均成績的前三的班級及其數(shù)學平均成績掉蔬。

思考一下,如果我們將上面語句改成查近,如下會怎樣眉踱?


我們發(fā)現(xiàn)阳懂,若將?avg(數(shù)學成績) > 75?放到WHERE子句中豺谈,此時GROUP BY語句還未執(zhí)行眨猎,因此此時聚合值?avg(數(shù)學成績)?還是未知的,因此會報錯戈泼。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市赏僧,隨后出現(xiàn)的幾起案子大猛,更是在濱河造成了極大的恐慌,老刑警劉巖淀零,帶你破解...
    沈念sama閱讀 212,080評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件挽绩,死亡現(xiàn)場離奇詭異,居然都是意外死亡驾中,警方通過查閱死者的電腦和手機唉堪,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,422評論 3 385
  • 文/潘曉璐 我一進店門模聋,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人唠亚,你說我怎么就攤上這事链方。” “怎么了灶搜?”我有些...
    開封第一講書人閱讀 157,630評論 0 348
  • 文/不壞的土叔 我叫張陵祟蚀,是天一觀的道長。 經(jīng)常有香客問我割卖,道長前酿,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,554評論 1 284
  • 正文 為了忘掉前任鹏溯,我火速辦了婚禮薪者,結果婚禮上,老公的妹妹穿的比我還像新娘剿涮。我一直安慰自己言津,他們只是感情好,可當我...
    茶點故事閱讀 65,662評論 6 386
  • 文/花漫 我一把揭開白布取试。 她就那樣靜靜地躺著悬槽,像睡著了一般。 火紅的嫁衣襯著肌膚如雪瞬浓。 梳的紋絲不亂的頭發(fā)上初婆,一...
    開封第一講書人閱讀 49,856評論 1 290
  • 那天,我揣著相機與錄音猿棉,去河邊找鬼磅叛。 笑死,一個胖子當著我的面吹牛萨赁,可吹牛的內容都是我干的弊琴。 我是一名探鬼主播,決...
    沈念sama閱讀 39,014評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼杖爽,長吁一口氣:“原來是場噩夢啊……” “哼敲董!你這毒婦竟也來了?” 一聲冷哼從身側響起慰安,我...
    開封第一講書人閱讀 37,752評論 0 268
  • 序言:老撾萬榮一對情侶失蹤腋寨,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后化焕,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體萄窜,經(jīng)...
    沈念sama閱讀 44,212評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,541評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了查刻。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片番宁。...
    茶點故事閱讀 38,687評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖赖阻,靈堂內的尸體忽然破棺而出蝶押,到底是詐尸還是另有隱情,我是刑警寧澤火欧,帶...
    沈念sama閱讀 34,347評論 4 331
  • 正文 年R本政府宣布棋电,位于F島的核電站,受9級特大地震影響苇侵,放射性物質發(fā)生泄漏赶盔。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,973評論 3 315
  • 文/蒙蒙 一榆浓、第九天 我趴在偏房一處隱蔽的房頂上張望于未。 院中可真熱鬧,春花似錦陡鹃、人聲如沸烘浦。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,777評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽闷叉。三九已至,卻和暖如春脊阴,著一層夾襖步出監(jiān)牢的瞬間握侧,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,006評論 1 266
  • 我被黑心中介騙來泰國打工嘿期, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留品擎,地道東北人。 一個月前我還...
    沈念sama閱讀 46,406評論 2 360
  • 正文 我出身青樓备徐,卻偏偏與公主長得像萄传,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子坦喘,可洞房花燭夜當晚...
    茶點故事閱讀 43,576評論 2 349

推薦閱讀更多精彩內容