1. 程式人生 > 其它 >SQL 執行順序

SQL 執行順序

⑨ SELECT ⑩ DISTINCT column,
⑥ AGG_FUNC(column or expression), ...
① FROM left_table
		③ JOIN right_table
		② ON tablename.column = other_tablename.column
④ WHERE constraint_expression
⑤ GROUP BY column
⑦ WITH CUBE|ROLLUP
⑧ HAVING constraint_expression
⑪ ORDER BY column ASC|DESC
⑫ LIMIT count OFFSET count;

FROM:笛卡爾積。

ON:主表保留。

JOIN:不符合 \(on\) 也新增。

WHERE:非聚合、非 \(select\) 別名。

GROUP BY:改變表的引用。

AGG_FUNC:聚合計算。

WITH\(cube\)\(rollup\)

HAVING:只作用分組後。

SELECT:選擇列、表示式計算。

DISTINCT:行去重。

ORDER BY:排序。

LIMIT:選擇指定數量行、數量列。

\(SQL\) 的執行順序發現,所有查詢語句都是從 \(from\) 開始。在執行過程中,每個步驟都會為下一個步驟生成一個虛擬表,這個虛擬表將作為下一個執行步驟的輸入。


1. from 執行笛卡爾積

\(from\)\(SQL\) 語句執行的第一步。對 \(from\) 子句中的表計算笛卡爾積(交叉聯接),生成虛擬表 \(t1\),獲取不同資料來源的資料集。

\(from\) 子句執行順序為從後到前,從左到右,\(from\) 子句中寫在最後的表(基礎表 \(driving\ table\))將被最先處理,即最後的表為驅動表,當 \(from\) 子句中包含多個表的情況下,需要選擇資料最少的表作為基礎表


2. on 篩選器

對虛擬表 \(t1\) 應用 \(on\) 篩選器,\(on\) 中的邏輯表示式將應用到虛擬表 \(t1\) 中各個行,篩選出滿足 \(on\)

邏輯表示式的行,生成虛擬表 \(t2\)


3. join 新增外部行

如果指定了 \(outer\ join\) 保留表中未找到匹配的行將作為外部行新增到虛擬表 \(t2\),生成虛擬表 \(t3\)。保留表如下:

  • \(left\ outer\ join\):把左表記為保留表。
  • \(right\ outer\ join\):把右表記為保留表。
  • \(full\ outer\ join\):把左右表都作為保留表。

在虛擬表 \(t2\) 的基礎上新增保留表中被過濾條件過濾掉的資料,非保留表中的資料被賦予 \(NULL\) 值,最後生成虛擬表 \(t3\)

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


4. where 篩選器

對虛擬表 \(t3\) 應用 \(where\) 篩選器。根據指定條件對資料進行篩選,並把滿足的資料插入虛擬表 \(t4\)

  • 由於資料還沒分組,所以還不能在 \(where\) 過濾器中使用聚合函式對分組統計的過濾。
  • 由於還沒進行列的選取操作,因此在 \(select\) 中使用列的別名也是不允許的。

5. group by 分組

\(group\ by\) 子句中的列/列表將虛擬表 \(t4\) 中的行唯一的值組合成一組,生成虛擬表 \(t5\)。如果應用了 \(group\ by\),那麼後面的所有步驟都只能得到虛擬表 \(t5\) 的列或聚合函式(\(count、sum、avg\) 等)。原因在於最終的結果集中只為每個組包含一行。

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


6. agg_func 計算聚合函式

常用聚合函式:\(avg、count、first、last、max、min、sum\)


7. with 應用 rollup或cube

對虛擬表 \(t5\) 應用 \(rollup\)\(cube\) 選項,生成虛擬表 \(t6\)

\(cube\)\(rollup\) 區別:

  • \(cube\) 生成的結果資料集顯示了所選列中值的所有組合的聚合。
  • \(rollup\) 生成的結果資料集顯示了所選列中值的某一層次結構的聚合。

8. having 篩選器

對虛擬表 \(t6\) 應用 \(having\) 篩選器。根據指定條件對資料進行篩選,並把滿足的資料插入虛擬表 \(t7\)

\(having\) 語句在 \(SQL\) 中的主要作用與 \(where\) 語句相同。但 \(having\) 是過濾聚合值,在 \(SQL\)增加 \(having\) 子句原因就是,\(where\) 關鍵字無法與聚合函式一起使用,\(having\) 子句主要和 \(group\ by\) 子句配合使用。


9. select 選出指定列

將虛擬表 \(t7\) 中的 \(select\) 中出現的列篩選出來,並對欄位進行處理,計算 \(select\) 句中的表示式,產生表 \(t8\)


10. distinct 行去重

將重複的行從虛擬表 \(t8\) 中移除,產生虛擬表 \(t9\)\(distinct\) 用來刪除重複行,只保留唯一的。


11. order by 排列

將虛擬表 \(t9\) 中的行按 \(order\ by\) 子句中的列/列表排序,生成遊標 \(t10\),注意不是虛擬表。因此使用 \(order\ by\) 子句查詢不能應用於表示式。同時,\(order\ by\) 子句的執行順序為從左到右排序,是非常消耗資源的。


12. limit/offset 指定返回行

\(t10\) 的開始處,選擇指定數量行,生成虛擬表 \(t11\),並返回呼叫者。