SQL語句執行順序


一、SQL語句執行順序

SQL查詢語句的執行順序解析

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

SQL查詢語句的執行順序解析

從這個順序中可以發現

所有的查詢語句都是從 FROM 開始執行的。在實際執行過程中,每個步驟都會為下一個步驟生成一個虛擬表,這個虛擬表將作為下一個執行步驟的輸入。

接下來,我們詳細的介紹下每個步驟的具體執行過程。

二、FROM:執行笛卡爾積

FROM 才是 SQL 語句執行的第一步,並非 SELECT 。對 FROM 子句中的前兩個表執行笛卡爾積(交叉聯接),生成虛擬表 VT1,獲取不同數據源的數據集。

FROM 子句執行順序為從后往前、從右到左,FROM 子句中寫在最后的表(基礎表 driving table)將被最先處理,即最后的表為驅動表,當 FROM 子句中包含多個表的情況下,我們需要選擇數據最少的表作為基礎表。

三、ON:應用ON過濾器

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

三、JOIN:添加外部行

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

  • LEFT OUTER JOIN 把左表記為保留表
  • RIGHT OUTER JOIN 把右表記為保留表
  • FULL OUTER JOIN 把左右表都作為保留表

在虛擬表 VT2 表的基礎上添加保留表中被過濾條件過濾掉的數據,非保留表中的數據被賦予 NULL 值,最后生成虛擬表 VT3

如果 FROM 子句包含兩個以上的表,則對上一個聯接生成的結果表和下一個表重復執行步驟1~3,直到處理完所有的表為止。

四、WHERE:應用 WEHRE 過濾器

對虛擬表 VT3 應用 WHERE 篩選器。根據指定的條件對數據進行篩選,並把滿足的數據插入虛擬表 VT4

  • 由於數據還沒有分組,因此現在還不能在 WHERE 過濾器中使用聚合函數對分組統計的過濾。
  • 同時,由於還沒有進行列的選取操作,因此在SELECT中使用列的別名也是不被允許的。

五、GROUP BY:分組

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

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

六、AGG_FUNC:計算聚合函數

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

  • AVG:返回平均值
  • COUNT:返回行數
  • FIRST:返回第一個記錄的值
  • LAST:返回最后一個記錄的值
  • MAX: 返回最大值
  • MIN:返回最小值
  • SUM: 返回總和

七、WITH:應用 ROLLUP 或 CUBE

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

CUBE 和 ROLLUP 區別如下:

  • CUBE 生成的結果數據集顯示了所選列中值的所有組合的聚合。
  • ROLLUP 生成的結果數據集顯示了所選列中值的某一層次結構的聚合。

八、HAVING:應用 HAVING 過濾器

對虛擬表 VT6 應用 HAVING 篩選器。根據指定的條件對數據進行篩選,並把滿足的數據插入虛擬表 VT7

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

九、SELECT:選出指定列

將虛擬表 VT7 中的在 SELECT 中出現的列篩選出來,並對字段進行處理,計算 SELECT 子句中的表達式,產生虛擬表 VT8

十、DISTINCT:行去重

將重復的行從虛擬表 VT8 中移除,產生虛擬表 VT9。DISTINCT 用來刪除重復行,只保留唯一的。

十一、ORDER BY:排列

將虛擬表 VT9 中的行按 ORDER BY 子句中的列/列表排序,生成游標 VC10 ,注意不是虛擬表。因此使用 ORDER BY 子句查詢不能應用於表達式。同時,ORDER BY 子句的執行順序為從左到右排序,是非常消耗資源的。

十二、LIMIT/OFFSET:指定返回行

從 VC10 的開始處選擇指定數量行,生成虛擬表 VT11,並返回調用者。

十三、實例

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

SQL查詢語句的執行順序解析

首先,我們先看下如上 SQL 的執行順序,如下:

  1. 首先執行 FROM 子句, 從學生成績表中組裝數據源的數據。
  2. 執行 WHERE 子句, 篩選學生成績表中所有學生的數學成績不為 NULL 的數據 。
  3. 執行 GROUP BY 子句, 把學生成績表按 "班級" 字段進行分組。
  4. 計算 avg 聚合函數, 按找每個班級分組求出 數學平均成績。
  5. 執行 HAVING 子句, 篩選出班級 數學平均成績大於 75 分的。
  6. 執行 SELECT 語句,返回數據,但別着急,還需要執行后面幾個步驟。
  7. 執行 ORDER BY 子句, 把最后的結果按 "數學平均成績" 進行排序。
  8. 執行 LIMIT ,限制僅返回3條數據。結合 ORDER BY 子句,即返回所有班級中數學平均成績的前三的班級及其數學平均成績。

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

SQL查詢語句的執行順序解析

我們發現,若將 avg(數學成績) > 75 放到 WHERE 子句中,此時 GROUP BY 語句還未執行,因此此時聚合值 avg(數學成績) 還是未知的,因此會報錯。

文章

軟件測試開發技術棧 - SQL查詢語句的執行順序解析


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM