博客 > SQL知識(shí):圖解SQL查詢處理的各個(gè)階段
瀏覽量:1309次評論:0次
作者:銳成網(wǎng)絡(luò)整理時(shí)間:2024-07-09 15:58:44
在SQL中,查詢處理是非常常見的操作,了解SQL查詢處理的各個(gè)階段,有助于我們更好的使用以提高工作效率。今天,我們將圖解SQL查詢處理的各個(gè)階段,便于大家理解SQL的執(zhí)行過程。
執(zhí)行順序
我們先用數(shù)字+關(guān)鍵字的方式標(biāo)注一下每個(gè)關(guān)鍵字的處理步驟。
(5)SELECT (5-2) DISTINCT (5-3) TOP(<top-specification>) (5-1) <select_list>
(1) FROM (1-J)<left_table><join_type> JOIN <right_table> ON <on_predicate>
|(1-A)<left_table><apply_type> APPLY <right_table_expression> AS <alias>
|(1-P)<left_table> PIVOT (<pivot_specification>) AS <alias>
|(1-U)<left_table> UNPIVOT (<unpivot_specification>) AS <alias>
(2) WHERE <where_predicate>
(3) GROUP BY <group_by_specification>
(4) HAVING <having_predicate>
(6) ORDER BY (order_by_list);
其中數(shù)字代表后面的關(guān)鍵字的執(zhí)行順序。
SQL與其它編程語言不同的最明顯特征就是代碼的執(zhí)行順序,在大多數(shù)編程語言中,代碼是按照編寫順序來執(zhí)行的,但在SQL中,第一個(gè)要執(zhí)行的子句是FROM子句,盡管SELECT 語句第一個(gè)出現(xiàn),但是幾乎總是放在最后執(zhí)行。
上述的執(zhí)行序號(hào)每一個(gè)都會(huì)生成一個(gè)虛表,生成的虛表會(huì)作為下一步的輸入來使用。這些生成的虛表對SQL發(fā)起者(客戶端應(yīng)用程序或者外部查詢)是不可用的,只有最后一步生成的虛表才會(huì)返回給SQL發(fā)起者。如果在查詢中沒有指定某一個(gè)子句,就會(huì)跳過相應(yīng)的步驟。
為方便大家理解,我們將每步的執(zhí)行過程以圖形的方式呈現(xiàn)給大家。
執(zhí)行順序解釋
相信大部分人對這些步驟不太理解,我們按順序?qū)ι厦娴牟襟E做個(gè)解讀。
(1)FROM
FROM 階段主要標(biāo)明查詢語句的來源表,如果是單表就表示不存在表運(yùn)算符會(huì)直接跳轉(zhuǎn)到WHERE子句;
如果存在表運(yùn)算符,則會(huì)根據(jù)每個(gè)表運(yùn)算符執(zhí)行一些列的子階段,例如,在連接運(yùn)算匯總涉及的階段有(1-J1)笛卡爾積、(1-J2) ON 篩選器和(1-J3) 添加外部行。這個(gè)階段FROM會(huì)生成虛表VT1。
(1-J1)笛卡爾積
這個(gè)階段對表運(yùn)算符涉及的兩個(gè)表執(zhí)行笛卡爾積(cross join),會(huì)生成虛表VT1-J1。
(1-J2)ON 篩選器
這個(gè)階段會(huì)對VT1-J1中生成的數(shù)據(jù)行根據(jù)ON字句(<on_predicate>)中出現(xiàn)的條件進(jìn)行篩選,只有當(dāng)滿足這些篩選條件的數(shù)據(jù)行,才會(huì)插入VT1-J2中。
(1-J3)添加外部行
如果指定了OUTER JOIN(通常指LEFT JOIN 和RIGHT JOIN),則會(huì)將主表(如果是LEFT JOIN主表就是左表,如果是RIGHT JOIN主表就是右表)中沒有匹配上的行,作為外部行添加到VT1-J2中,生成VT1-J3。
注:這一部分我會(huì)在后續(xù)的章節(jié)中給大家詳細(xì)講解外部行的添加過程
其它的運(yùn)算符APPLY,PIVOT和UNPIVOT的處理過程與JOIN類似,我們就不再一一演示
通過上述各個(gè)子階段的執(zhí)行,最終生成虛表VT1.
(2)WHERE
在WHERE這個(gè)階段,會(huì)對VT1中的數(shù)據(jù)行進(jìn)行條件篩選,同樣是只有滿足WHERE子句的數(shù)據(jù)行,才會(huì)被插入到虛表VT2中。
(3)GROUP BY
在GROUP BY階段,按照GROUP BY子句中指定的列名,將VT2中的行進(jìn)行分組,生成VT3,最終每個(gè)分組只有幾個(gè)結(jié)果行。
(4)HAVING
在HAVING階段,根據(jù)HAVING子句中出現(xiàn)的條件(通常是聚合函數(shù)條件,如果sum(),count(),min(),max()等)對VT3中的分組進(jìn)行篩選,只有滿足HAVING子句的條件的數(shù)據(jù)行,才會(huì)被插入到VT4中。
(5)SELECT
處理SELECT子句中的元素,產(chǎn)生VT5,如果SELECT后面沒有DISTINCT或TOP則直接跳轉(zhuǎn)到ORDER BY子句
如果有DISTINCT或TOP子句則與FROM類似,需要執(zhí)行一系列的子階段
(5-1)計(jì)算表達(dá)式
計(jì)算SELECT列表中的表達(dá)式,通常是做一些列運(yùn)算,如列之間簡單的加減乘除或列拼接等(聚合函數(shù)運(yùn)算也屬于列的加減乘除),這階段會(huì)生成虛表VT5-1
(5-2)DISTINCT
這個(gè)子階段會(huì)刪除VT5-1中的重復(fù)行,生成虛表VT5-2
(5-3)TOP
這里需要注意,TOP執(zhí)行階段會(huì)根據(jù)ORDER BY子句定義的邏輯順序,從VT5-2中選擇前面指定數(shù)量或百分比的數(shù)據(jù)行,生成VT5-3。
換言之實(shí)際上是有一個(gè)排序ORDER BY的過程在TOP前面,但是這個(gè)排序的過程我們通常是指發(fā)生在子查詢中階段。例如
SELECT * FROM
(
SELECT TOP 10 userid,username
FROM tablename
ORDER BY userid
) t
ORDER BY t.username
這里的子查詢t表里的TOP 1是在對userid先排序后再取前10條記錄,而如果沒有這個(gè)子查詢,TOP直接在最外層,那么首先執(zhí)行的應(yīng)該是ORDER BY,而不是TOP,這里大家需要特別注意。
SELECT TOP 10 userid,username
FROM tablename
ORDER BY userid
(6) ORDER BY
根據(jù)ORDER BY子句中指定的列名,對VT5(VT5-3)中的行進(jìn)行排序,生成游標(biāo)VT6
至此,整個(gè)SQL查詢過程執(zhí)行結(jié)束,最終返回VT6的結(jié)果給SQL發(fā)起者。
重要聲明:本文來自SQL數(shù)據(jù)庫開發(fā),經(jīng)授權(quán)轉(zhuǎn)載,版權(quán)歸原作者所有,不代表銳成觀點(diǎn),轉(zhuǎn)載的目的在于傳遞更多知識(shí)和信息。
相關(guān)文章推薦
2025-05-27 11:53:22
2024-08-20 17:58:16
2024-08-19 17:49:29
2024-08-19 10:23:28
2024-08-16 17:06:33
熱門工具
標(biāo)簽選擇
閱讀排行
我的評論
還未登錄?點(diǎn)擊登錄