SQL 查詢的執行順序

来源:https://www.cnblogs.com/emanjusaka/archive/2023/09/04/page_6.html
-Advertisement-
Play Games

瞭解 SQL 查詢的執行順序對我們解決一些問題很有幫助,有時我們可能會疑惑為什麼不能對分組的結果進行篩選這樣類似的問題?之前一直不是理解這個問題,在瞭解了SQL 查詢的執行順序之後這個問題也就迎刃而解。在我們對 SQL 查詢語句進行分析優化時,掌握執行順序也是有一定幫助的。 ...


by emanjusaka from ​ https://www.emanjusaka.top/archives/6 彼岸花開可奈何
本文歡迎分享與聚合,全文轉載請留下原文地址。

前言

瞭解 SQL 查詢的執行順序對我們解決一些問題很有幫助,有時我們可能會疑惑為什麼不能對分組的結果進行篩選這樣類似的問題?之前一直不是理解這個問題,在瞭解了SQL 查詢的執行順序之後這個問題也就迎刃而解。在我們對 SQL 查詢語句進行分析優化時,掌握執行順序也是有一定幫助的。

一、理論順序

SQL 執行順序

上面是圖示 SQL 的執行順序,下麵用列表列出:

  1. FROM
  2. ON
  3. JOIN
  4. WHERE
  5. GROUP BY
  6. CUBE | ROLLUP
  7. HAVING
  8. SELECT
  9. DISTINCT
  10. ORDER BY
  11. LIMIT

上面所列出的執行順序能幫助我們解答一些問題:

  • 為啥不能對視窗函數的執行結果進行過濾?

    因為視窗函數在 SELECT 步驟執行,而這步是在 WHERE 和 GROUP BY 之後

  • 可以對分組的結果進行篩選嗎?

    不可以,因為 GROUP BY 在 WHERE 之後執行

  • 可以對分組後的結果進行排序嗎?

    可以,因為 ORDER BY 在 GROUP BY 之後。

二、代碼示例

  • 學生表

    image

  • 成績表

    image

  • 查詢語句

    查詢來自天津且總成績高於70分,並且查詢他們的總成績,查詢結果按成績降序排列

    SELECT
    	ss.student_id,sum(se.grade) as total,ss.city
    FROM
    	students ss
    	LEFT JOIN score se ON ss.student_id = se.student_id 
    WHERE
    	ss.city = "天津"
    GROUP BY ss.student_id
    HAVING sum(se.grade) > 70
    ORDER BY total DESC
    LIMIT 10
    
  • 查詢結果

    image

三、分析 SQL 執行過程

SQL 運行的每個操作都會產生一張虛擬表,只不過這些虛擬表對用戶是透明的,只有最後一步生成的虛擬表才會返回給用戶。

  1. 第一步執行的是對 FROM 字句前後的兩張表 students 和 score 進行笛卡爾積操作,生成虛擬表VT1。

  2. 應用 ON 過濾器

    在虛擬表 VT1 中執行過濾操作,過濾條件為:ss.student_id = se.student_id ​

    對於在 ON 過濾條件下的 NULL 值比較,此時的比較結果為 UNKNOWN,卻被視為 FALSE 來進行處理,即兩個 NULL 並不相同。但是在下麵兩種情況下認為兩個 NULL 值的比較是相等的:

    • GROUP BY 子句把所有 NULL 值分到同一組
    • ORDER BY 子句中把所有 NULL 值排列在一起

    在產生虛擬表 VT2 時,會增加一個額外的列來表示 ON 過濾條件的返回值,返回值有 TRUE、FALSE、UNKNOWN。取出比較值為 TRUE 的記錄,產生虛擬表 VT2。

  3. 添加外部行

    這一步只有在連接類型為 OUTER JOIN 時才發生,如 LEFT OUTER JOIN、RIGHT OUTERJOIN、FULL OUTER JOIN。雖然在大多數時候我們可以省略 OUTER 關鍵字,但 OUTER 代表的就是外部行。LEFT OUTER JOIN 把左表記為保留表,RIGHT OUTER JOIN 把右表記為保留表,FULL OUTER JOIN 把左右表都記為保留表。添加外部行的工作就是在 VT2 表的基礎上添加保留表中被過濾條件過濾掉的數據,非保留表中的數據被賦予 NULL 值,最後生成虛擬表 VT3

  4. 應用 WHERE 過濾器

    對上一步驟產生的虛擬表 VT3 進行 WHERE 條件過濾,只有符合<where_condition>的記錄才會輸出到虛擬表 VT4 中

    在當前應用 WHERE 過濾器時,有兩種過濾是不被允許的:

    • 由於數據還沒有分組,因此現在還不能在 WHERE 過濾器中使用 where_condition=MIN(col)這類對統計的過濾
    • 由於沒有進行列的選取操作,因此在 SELECT 中使用列的別名也是不被允許的,如 SELECT city as c from students WHERE c = '天津' 是不允許出現的
  5. 分組

    在本步驟中根據指定的列對上個步驟中產生的虛擬表進行分組,最後得到虛擬表 VT5

  6. 應用 HAVING 過濾器

    在該步驟中對於上一步產生的虛擬表應用 HAVING 過濾器,HAVING 是對分組條件進行過濾的篩選器。生成虛擬表VT6。

  7. 處理 SELECT 列表

    在這一步中,將 SELECT 中指定的列從上一步產生的虛擬表中選出生成虛擬表 VT7。

  8. 應用 ORDER BY 字句

    根據 ORDER BY 子句中指定的列對上一步輸出的虛擬表進行排列,返回新的虛擬表 VT8。

    註意:在 MySQL 資料庫中,NULL 值在升序過程中總是首先被選出,即 NULL 值在 ORDER BY 子句中被視為最小值

  9. LIMIT 子句

    在該步驟中應用 LIMIT 子句,從上一步驟的虛擬表中選出從指定位置開始的指定行數據。對於沒有應用 ORDER BY 的 LIMIT 子句,結果同樣可能是無序的,因此 LIMIT 子句通常和 ORDER BY 子句一起使用。

四、註意

上面所討論的順序皆為理論上的執行順序,實際上資料庫引擎並不是通過連接、過濾和分組來運行查詢,因為它實現了一系列優化來提升查詢速度(不影響最終的返回結果)。資料庫引擎可能會為了提高查詢的速度把一些過濾條件進行提前,當然前提是不會對返回的結果造成影響。

SELECT
	ss.student_id,sum(se.grade) as total,ss.city
FROM
	students ss
	LEFT JOIN score se ON ss.student_id = se.student_id 
WHERE
	ss.city = "天津"

這個 sql 學生城市是天津的只有三個,如果在學生很多的情況下如果先做城市的篩選後再對兩張表做笛卡爾積可以很大程度的提升性能,並且也不會對返回的結果造成影響。這時實際上SQL的執行順序可能就與理論上的執行順序不一樣了。

參考資料

  1. SQL queries don't start with SELECT

本文原創,才疏學淺,如有紕漏,歡迎指正。尊貴的朋友,如果本文對您有所幫助,歡迎點贊,並期待您的反饋,以便於不斷優化。

原文地址: https://www.emanjusaka.top/archives/6

微信公眾號:emanjusaka的編程棧


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • ![](https://img2023.cnblogs.com/blog/3076680/202309/3076680-20230904164459431-1322523641.png) # 1. 儘管SQL標準指定了部分函數,但資料庫廠商並沒有遵循這些函數規範 # 2. 字元串 ## 2.1. c ...
  • 1. SQL語句類型 1. DDL(Data Definition Language,數據定義語言): DDL語句用於定義資料庫對象(如表、索引、視圖等)。常見的DDL語句包括: CREATE:用於創建資料庫對象,如創建表、索引、視圖等。 ALTER:用於修改資料庫對象的結構,如修改表的列、添加約束 ...
  • Redis OSS的邏輯資料庫,無論是自部署還是作為ElastiCache等托管服務啟動,其目的都是通過減少管理需求並提供一系列的預設設置來簡化開發人員的工作。然而,在實際生產中,當您的功能和操作需求發生變化時,單個Redis實例可能不再足夠。 ...
  • 如今隨著互聯網技術快速發展,業務越來越複雜,系統的高併發和關鍵數據的場景越來越多。在分散式系統中,機器宕機和消息丟失也是需要重點關註的問題,其中的一個典型就是冪等性問題。 ...
  • 伺服器顯卡在高性能計算和人工智慧應用中扮演著至關重要的角色。高性能計算廣泛應用於科學計算、工程設計、氣象預測等領域,而人工智慧應用則涵蓋了機器學習、深度學習、圖像識別等領域。這些應用需要大量的計算資源和高效的演算法來處理大規模的數據集,而伺服器顯卡正是在這樣的應用中發揮重要作用。 ...
  • 為解決用戶面臨的 MongoDB 遷移問題,玖章算術旗下的雲原生智能數據管理平臺 NineData 推出了 MongoDB 業務不停服數據遷移能力。NineData 實現了完全自動化的全量數據遷移,以及增量數據的採集複製能力。 ...
  • 本文簡單介紹了讀寫分離架構,和出現主從延遲後,如果我們用的讀寫分離的架構,那麼我們應該怎麼處理這種情況,相信在日常我們的主從還是或多或少的存在延遲。上面介紹的幾種方案,有些方案看上去十分不靠譜,有些方案做了一些妥協,但是都有實際的應用場景,需要我們根據自身的業務情況,合理選擇對應的方案。 ...
  • 本文分享自華為雲社區《直播回顧 | 數倉資源管控理論已掌握,是時候實戰了》,作者:胡辣湯 。 混合負載場景下,如何高效運維資料庫,防止資料庫系統過載?GaussDB(DWS)資源管控為資料庫平穩可靠運行提供了哪些助力?本期《數倉專家手把手教您資源管控與運維實戰》的主題直播中,我們邀請到華為雲Gaus ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...