SQL 查詢總是先執行SELECT語句嗎?你們都錯了!

2021-03-02 Android編程精選
infoq.cn/article/Oke8hgilga3PTZ3gWvbg很多 SQL 查詢都是以 SELECT 開始的。不過,最近我跟別人解釋什麼是窗口函數,我在網上搜索」是否可以對窗口函數返回的結果進行過濾「這個問題,得出的結論是」窗口函數必須在 WHERE 和 GROUP BY 之後,所以不能」。於是我又想到了另一個問題:SQL 查詢的執行順序是怎樣的?好像這個問題應該很好回答,畢竟自己已經寫了上萬個 SQL 查詢了,有一些還很複雜。但事實是,我仍然很難確切地說出它的順序是怎樣的。SQL 查詢的執行順序於是我研究了一下,發現順序大概是這樣的。SELECT 並不是最先執行的,而是在第五個。這張圖回答了以下這些問題這張圖與 SQL 查詢的語義有關,讓你知道一個查詢會返回什麼,並回答了以下這些問題:可以在 GRROUP BY 之後使用 WHERE 嗎?(不行,WHERE 是在 GROUP BY 之前!)可以對窗口函數返回的結果進行過濾嗎?(不行,窗口函數是 SELECT 語句裡,而 SELECT 是在 WHERE 和 GROUP BY 之後)可以基於 GROUP BY 裡的東西進行 ORDER BY 嗎?(可以,ORDER BY 基本上是在最後執行的,所以可以基於任何東西進行 ORDER BY)但資料庫引擎並不一定嚴格按照這個順序執行 SQL 查詢,因為為了更快地執行查詢,它們會做出一些優化,這些問題會在以後的文章中解釋。如果你想要知道一個查詢語句是否合法,或者想要知道一個查詢語句會返回什麼,可以參考這張圖;在涉及查詢性能或者與索引有關的東西時,這張圖就不適用了。混合因素:列別名

SELECT CONCAT(first_name, ' ', last_name) AS full_name, count(*)
FROM table
GROUP BY full_name

從這個語句來看,好像 GROUP BY 是在 SELECT 之後執行的,因為它引用了 SELECT 中的一個別名。但實際上不一定要這樣,資料庫引擎可以把查詢重寫成這樣:

SELECT CONCAT(first_name, ' ', last_name) AS full_name, count(*)
FROM table
GROUP BY CONCAT(first_name, ' ', last_name)

資料庫引擎還會做一系列檢查,確保 SELECT 和 GROUP BY 中的東西是有效的,所以會在生成執行計劃之前對查詢做一次整體檢查。資料庫可能不按照這個順序執行查詢(優化)在實際當中,資料庫不一定會按照 JOIN、WHERE、GROUP BY 的順序來執行查詢,因為它們會進行一系列優化,把執行順序打亂,從而讓查詢執行得更快,只要不改變查詢結果。

SELECT * FROM
owners LEFT JOIN cats ON owners.id = cats.owner
WHERE cats.name = 'mr darcy'

如果只需要找出名字叫「mr darcy」的貓,那就沒必要對兩張表的所有數據執行左連接,在連接之前先進行過濾,這樣查詢會快得多,而且對於這個查詢來說,先執行過濾並不會改變查詢結果。資料庫引擎還會做出其他很多優化,按照不同的順序執行查詢,不過我並不是這方面的專家,所以這裡就不多說了。LINQ 的查詢以 FROM 開頭LINQ(C#和 VB.NET 中的查詢語法)是按照 FROM…WHERE…SELECT 的順序來的。這裡有一個 LINQ 查詢例子:

var teenAgerStudent = from s in studentList
                      where s.Age > 12 && s.Age < 20
                      select s;

pandas 中的查詢也基本上是這樣的,不過你不一定要按照這個順序。我通常會像下面這樣寫 pandas 代碼:

df = thing1.join(thing2)      # JOIN
df = df[df.created_at > 1000] # WHERE
df = df.groupby('something', num_yes = ('yes', 'sum')) # GROUP BY
df = df[df.num_yes > 2]       # HAVING, 對 GROUP BY 結果進行過濾
df = df[['num_yes', 'something1', 'something']] # SELECT, 選擇要顯示的列
df.sort_values('sometthing', ascending=True)[:30] # ORDER BY 和 LIMIT
df[:30]

這樣寫並不是因為 pandas 規定了這些規則,而是按照 JOIN/WHERE/GROUP BY/HAVING 這樣的順序來寫代碼會更有意義些。不過我經常會先寫 WHERE 來改進性能,而且我想大多數資料庫引擎也會這麼做。

相關焦點

  • SQL 查詢語句先執行 SELECT?兄弟你認真的麼?
    具體解釋:(註:下面「VT」表示 → 虛擬表 virtual )from:select * from table_1, table_2; 與 select * from table_1 join table_2; 的結果一致,都是表示求笛卡爾積;用於直接計算兩個表笛卡爾積,得到虛擬表VT1,這是所有select語句最先執行的操作
  • 面試官:你知道select語句和update語句分別是怎麼執行的嗎?
    來自:黎社編程(ID:  LDCldc123095)最近有粉絲面試網際網路公司被問到:你知道select語句和update語句分別是怎麼執行的嗎?,要我寫一篇這兩者執行SQL語句的區別,這不就來了。注意:後續的一些列操作都是依賴於這個權限的範圍內的。檢索緩存當建立連接,履行查詢語句的時候,會先行檢查在緩存區域看看這個sql與否履行過,若是之前執行過,它的執行結果會以Key-Value的形式緩存於內存中,Key是執行的sql,Value是結果集。
  • 面試官:你知道 select 語句和 update 語句分別是怎麼執行的嗎?
    select語句和update語句分別是怎麼執行的嗎?注意:後續的一些列操作都是依賴於這個權限的範圍內的。檢索緩存當建立連接,履行查詢語句的時候,會先行檢查在緩存區域看看這個sql與否履行過,若是之前執行過,它的執行結果會以Key-Value的形式緩存於內存中,Key是執行的sql,Value是結果集。
  • Mysql中一條SQL查詢語句是如何執行的?
    2.查詢流程解析select * from table1 where ID=10;這條語句相信大家再熟悉不過了,下面我們就看看這一條語句在mysql中是怎麼執行的。第一步:一條sql語句要經過連接器,客戶端要和mysql建立連接。
  • Oracle優化:sql語句的執行順序
    理解 sql 語句的執行順序對我們優化 sql 有很大的幫助,那麼 sql 語句的執行順序是怎樣的呢,以一條簡單的的語句做分析:① 先執行 from 子句,明確數據的來源,從哪個表或哪個視圖來查詢② 接著執行
  • MySQL-SQL語句執行流程
    查詢緩存:  執行查詢語句的時候,會先查詢緩存(MySQL 8.0 版本後移除,因為這個功能不太實用)。分析器:  沒有命中緩存的話,SQL 語句就會經過分析器,分析器說白了就是要先看你的 SQL 語句要幹嘛,再檢查你的 SQL 語句語法是否正確。
  • Select * from user的千層套路——一個sql是如何執行的
    Select * from user的千層套路    作為一個程式設計師,可以說是無時無刻不與sql語句進行打交道,可是你真的了解MySQl的基本框架嗎?以及你所寫的每一條SQL是如何運行的嗎?就比如下面這條平平無奇的SQL語句:select * from user where id='1';    對於這麼一條簡單的不能再簡單的sql語句來說mysql伺服器做了哪些處理呢?
  • MySQL數據查詢select語句靈活使用詳解
    案例:查詢用戶表user的所有信息Select * from user第二種:帶有條件篩選的單表查詢 where這個語法只是在select查詢語句的最好加上一條where語句進行數據的進一步過濾。第四種:過濾相同列數據 distinct如果我們得到的查詢結果中有相同的數據行,我們可以通過distinct關鍵詞進行過濾。語法結構:select distinct 欄位 from 表沒錯,只需要在查詢select關鍵詞後加上distinct關鍵詞即可。舉例:查詢用戶表一共有哪些用戶暱稱。
  • mysql常用sql語句總結
    (嵌套查詢)三種子查詢 :where子查詢、from子查詢、exists子查詢where子查詢先執行where後的語句,得到內層結果。再執行外層語法:select 欄位 from 表 where 內層結果eg:select goods_name,goods_id from goods where goods_id =(select max(goods_id) from goods);from子查詢先執行from後的語句,得到內層結果。
  • 深入淺出SQL嵌套SELECT語句
    嵌套SELECT語句也叫子查詢,形如:SELECT name FROM bbc WHERE region = (SELECT region FROM bbc WHERE name = 'Brazil')一個SELECT語句的查詢結果可以作為另一個語句的輸入值。
  • 優化SQL查詢:如何寫出高性能SQL語句
    執行計劃是資料庫根據SQL語句和相關表的統計信息作出的一個查詢方案,這個方案是由查詢優化器自動分析產生的,比如一條SQL語句如果用來從一個 10萬條記錄的表中查1條記錄,那查詢優化器會選擇「索引查找」方式,如果該表進行了歸檔,當前只剩下5000條記錄了,那查詢優化器就會改變方案,採用 「全表掃描」方式。
  • 「MySQL系列」分析Sql執行時間及查詢執行計劃(附資料庫和一千萬數據)
    接下來這篇文章我們來看看如何分析我們的sql執行效率。首先找到執行慢的sql,然後對執行慢的SQL進行分析。在分析之前是不是有這樣的困惑,我的數據量這麼少。我如何分析SQL執行效率。不要慌,我們已準備了一千萬條數據。接下來看看如何將這一千萬條數據快速導入到資料庫中。
  • 最強解讀MyBatis是如何執行SQL語句的?
    MyBatis 如何獲取 sql 語句?MyBatis 如何執行 sql 語句?MyBatis 如何實現不同類型數據之間的轉換?在過去程式設計師使用JDBC連接資料庫,總會帶來諸多不便。MyBatis 如何獲取 sql 語句? 與獲取資料庫源類似,只要解析Mapper配置文件中的對應標籤,就可以獲得對應的sql語句。
  • 資料庫之SQL查詢語句
    和事務相關,執行完後需要經過事務控制語句提交後才能真正的將改變應用到資料庫中。包括:INSERT:將數據插入到數據表中UPDATE:更新數據表中已存在的數據DELETE:刪除數據表中的數據(3) 事務控制語言(TCL):Transaction Control Language用來維護數據一致性的語句。
  • 用Select×進行SQL查詢的七宗罪
    【51CTO.com快譯】如今,網上許多文章都已明確地指出:使用「SELECT * 」作為SQL查詢方式是一種極其危險的代碼書寫習慣。開發人員應該儘量在自己的程序中避免出現此類查詢,取而代之的應該是明確地指定要查詢的列名。不過,大家可能只是「知其然,而不知其所以然」。
  • MySQL資料庫SQL查詢優化技巧之SELECT
    查詢語法和使用方法,以及SELECT的執行流程,了解了SELECT的執行流程還是很重要的,重要我們才能有針對性地去進行優化,比如select在執行的時候 會把所以的欄位編程成大寫字母,這樣我們在起初編寫SELECT語句時就可以把所以的字母進行大寫,這樣就省去了程序為把SQL語句變成大寫的消耗,速度自然就會提高。
  • SQL語句之Select
    既然Select語句執行的結果也是一張表,那麼它的語句中就應該指明產生這張表的欄位和記錄。Select關鍵詞後指明所需要的欄位,From關鍵詞指明數據的來源。語句1:select 姓名,成績 from 學生,成績 where 學生.學號=成績.學號語句2:select 姓名,成績 from 學生 join 成績 on 學生.學號=成績.學號例9:查詢各個學生所修課程的課程名、成績語句1:select 姓名,課程名,成績 from 學生,成績,課程 where 學生.
  • 學習MySQL的select語句
    select語句可 以用回車分隔$sql="select * from article where id=1"和  $sql="select * from article where id=1">都可以得到正確的結果,但有時分開寫或許能 更明了一點,特別是當sql語句比較長時。
  • 一道簡單的sql語句題
    1信心滿滿地運行,發現 報錯了!百度了一下,這好像是mysql5.7版本的新特性,按照網上的方法,執行如下的sql語句就可以取消這個模式:SET sql_mode ='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION';
  • 基礎SQL-DQL語句-SELECT查詢的簡單使用以及IFNULL函數
    基礎SQL-DQL語句-SELECT查詢的簡單使用以及IFNULL函數分類描述關鍵字DQL(Data Query Language)數據查詢語言 (掌握)DQL語言並不是屬於MYSQL官方的分類,但是對資料庫的操作最多就是查詢,所以我們的程式設計師把查詢語句的語句稱作為DQL語言SELECT 等查詢不會對資料庫中的數據進行修改.只是一種顯示數據的方式