1. 程式人生 > >MySQL的 SQL邏輯查詢語句執行順序

MySQL的 SQL邏輯查詢語句執行順序

最後,這篇文章是我讀《MySQL技術內幕:SQL程式設計》而總結出來的,對於書中有的東西講的比較“粗”,可能是我的水平沒有達到人家作者要求的水平,導致閱讀起來,不是很舒服,所以,這篇博文,將會非常細緻的進行總結。只有你想不到,沒有你做不到。

能看懂麼?

先來一段虛擬碼,首先你能看懂麼?

SELECT DISTINCT <select_list>
FROM <left_table><join_type> JOIN <right_table>
ON <join_condition>
WHERE <where_condition>
GROUP BY 
<group_by_list> HAVING <having_condition> ORDER BY <order_by_condition> LIMIT <limit_number>

如果你知道每個關鍵字的意思,作用,如果你還用過的話,那再好不過了。但是,你知道這些語句,它們的執行順序你清楚麼?如果你非常清楚,你就沒有必要再浪費時間繼續閱讀了;如果你不清楚,非常好,你應該慶幸你閱讀到了這麼好的一篇文章。

準備工作

首先宣告下,一切測試操作都是在MySQL資料庫上完成,關於MySQL資料庫的一些簡單操作,請閱讀一下文章:

繼續做以下的前期準備工作:

  1. 新建一個測試資料庫TestDB;
      create database 
    TestDB;
  2. 建立測試表table1和table2;
     CREATE TABLE table1
     (
         customer_id VARCHAR(10) NOT NULL,
         city VARCHAR(10) NOT NULL,
         PRIMARY KEY(customer_id)
     )ENGINE=INNODB DEFAULT CHARSET=UTF8;
    
     CREATE TABLE table2
     (
         order_id INT NOT NULL auto_increment,
         customer_id VARCHAR(10),
         PRIMARY KEY(order_id)
     )ENGINE=INNODB DEFAULT CHARSET=UTF8;
  3. 插入測試資料;
     INSERT INTO table1(customer_id,city) VALUES('163','hangzhou');
     INSERT INTO table1(customer_id,city) VALUES('9you','shanghai');
     INSERT INTO table1(customer_id,city) VALUES('tx','hangzhou');
     INSERT INTO table1(customer_id,city) VALUES('baidu','hangzhou');
    
     INSERT INTO table2(customer_id) VALUES('163');
     INSERT INTO table2(customer_id) VALUES('163');
     INSERT INTO table2(customer_id) VALUES('9you');
     INSERT INTO table2(customer_id) VALUES('9you');
     INSERT INTO table2(customer_id) VALUES('9you');
     INSERT INTO table2(customer_id) VALUES('tx');
     INSERT INTO table2(customer_id) VALUES(NULL);

    準備工作做完以後,table1和table2看起來應該像下面這樣:

     mysql>select*from table1;+-------------+----------+| customer_id | city     |+-------------+----------+|163| hangzhou ||9you| shanghai || baidu       | hangzhou || tx          | hangzhou |+-------------+----------+4 rows inset(0.00 sec)
    
     mysql>select*from table2;+----------+-------------+| order_id | customer_id |+----------+-------------+|1|163||2|163||3|9you||4|9you||5|9you||6| tx          ||7| NULL        |+----------+-------------+7 rows inset(0.00 sec)
  4. 準備SQL邏輯查詢測試語句
     SELECT a.customer_id, COUNT(b.order_id)as total_orders
     FROM table1 AS a
     LEFT JOIN table2 AS b
     ON a.customer_id = b.customer_id
     WHERE a.city ='hangzhou'
     GROUP BY a.customer_id
     HAVING count(b.order_id)<2
     ORDER BY total_orders DESC;

    使用上述SQL查詢語句來獲得來自杭州,並且訂單數少於2的客戶。

好吧,這些測試表和測試資料均來自《MySQL技術內幕:SQL程式設計》,這應該不算抄襲吧,借鑑借鑑啊。

萬事俱備,只欠東風。接下來開始這篇文章最正式的部分吧。

SQL邏輯查詢語句執行順序

還記得上面給出的那一長串的SQL邏輯查詢規則麼?那麼,到底哪個先執行,哪個後執行呢?現在,我先給出一個查詢語句的執行順序:

(7)     SELECT 
(8)     DISTINCT <select_list>(1)     FROM <left_table>(3)<join_type> JOIN <right_table>(2)     ON <join_condition>(4)     WHERE <where_condition>(5)     GROUP BY <group_by_list>(6)     HAVING <having_condition>(9)     ORDER BY <order_by_condition>(10)    LIMIT <limit_number>

上面在每條語句的前面都標明瞭執行順序號,不要問我怎麼知道這個順序的。我也是讀各種“武林祕籍”才得知的,如果你有功夫,去閱讀一下MySQL的原始碼,也會得出這個結果的。

好了,上面我標出了各條查詢規則的執行先後順序,那麼各條查詢語句是如何執行的呢?這就是我今天這篇博文的重點內容。Go on…

執行FROM語句

在這些SQL語句的執行過程中,都會產生一個虛擬表,用來儲存SQL語句的執行結果(這是重點),我現在就來跟蹤這個虛擬表的變化,得到最終的查詢結果的過程,來分析整個SQL邏輯查詢的執行順序和過程。

第一步,執行FROM語句。我們首先需要知道最開始從哪個表開始的,這就是FROM告訴我們的。現在有了<left_table><right_table>兩個表,我們到底從哪個表開始,還是從兩個表進行某種聯絡以後再開始呢?它們之間如何產生聯絡呢?——笛卡爾積

關於什麼是笛卡爾積,請自行Google補腦。經過FROM語句對兩個表執行笛卡爾積,會得到一個虛擬表,暫且叫VT1(vitual table 1),內容如下:

+-------------+----------+----------+-------------+| customer_id | city     | order_id | customer_id |+-------------+----------+----------+-------------+|163| hangzhou |1|163||9you| shanghai |1|163|| baidu       | hangzhou |1|163|| tx          | hangzhou |1|163||163| hangzhou |2|163||9you| shanghai |2|163|| baidu       | hangzhou |2|163|| tx          | hangzhou |2|163||163| hangzhou |3|9you||9you| shanghai |3|9you|| baidu       | hangzhou |3|9you|| tx          | hangzhou |3|9you||163| hangzhou |4|9you||9you| shanghai |4|9you|| baidu       | hangzhou |4|9you|| tx          | hangzhou |4|9you||163| hangzhou |5|9you||9you| shanghai |5|9you|| baidu       | hangzhou |5|9you|| tx          | hangzhou |5|9you||163| hangzhou |6| tx          ||9you| shanghai |6| tx          || baidu       | hangzhou |6| tx          || tx          | hangzhou |6| tx          ||163| hangzhou |7| NULL        ||9you| shanghai |7| NULL        || baidu       | hangzhou |7| NULL        || tx          | hangzhou |7| NULL        |+-------------+----------+----------+-------------+

總共有28(table1的記錄條數 * table2的記錄條數)條記錄。這就是VT1的結果,接下來的操作就在VT1的基礎上進行。

執行ON過濾

執行完笛卡爾積以後,接著就進行ON a.customer_id = b.customer_id條件過濾,根據ON中指定的條件,去掉那些不符合條件的資料,得到VT2表,內容如下:

+-------------+----------+----------+-------------+| customer_id | city     | order_id | customer_id |+-------------+----------+----------+-------------+|163| hangzhou |1|163||163| hangzhou |2|163||9you| shanghai |3|9you||9you| shanghai |4|9you||9you| shanghai |5|9you|| tx          | hangzhou |6| tx          |+-------------+----------+----------+-------------+

VT2就是經過ON條件篩選以後得到的有用資料,而接下來的操作將在VT2的基礎上繼續進行。

新增外部行

這一步只有在連線型別為OUTER JOIN時才發生,如LEFT OUTER JOINRIGHT OUTER JOINFULL OUTER JOIN。在大多數的時候,我們都是會省略掉OUTER關鍵字的,但OUTER表示的就是外部行的概念。

LEFT OUTER JOIN把左表記為保留表,得到的結果為:

+-------------+----------+----------+-------------+| customer_id | city     | order_id | customer_id |+-------------+----------+----------+-------------+|163| hangzhou |1|163||163| hangzhou |2|163||9you| shanghai |3|9you||9you| shanghai |4|9you||9you| shanghai |5|9you|| tx          | hangzhou |6| tx          || baidu       | hangzhou |     NULL | NULL        |+-------------+----------+----------+-------------+

RIGHT OUTER JOIN把右表記為保留表,得到的結果為:

+-------------+----------+----------+-------------+| customer_id | city     | order_id | customer_id |+-------------+----------+----------+-------------+|163| hangzhou |1|163||163| hangzhou |2|163||9you| shanghai |3|9you||9you| shanghai |4|9you||9you| shanghai |5|9you|| tx          | hangzhou |6| tx          || NULL        | NULL     |7| NULL        |+-------------+----------+----------+-------------+

FULL OUTER JOIN把左右表都作為保留表,得到的結果為:

+-------------+----------+----------+-------------+| customer_id | city     | order_id | customer_id |+-------------+----------+----------+-------------+|163| hangzhou 
            
           

相關推薦

python 3 mysql sql邏輯查詢語句執行順序

shanghai 不能 結果 utf8 才會 right 完成 並且 分享 python 3 mysql sql邏輯查詢語句執行順序 一 、SELECT語句關鍵字的定義順序 SELECT DISTINCT <select_list> FROM <left

mysql五補充部分:SQL邏輯查詢語句執行順序

std data 根據 使用 cor 分析 執行過程 笛卡爾 不同的 閱讀目錄 一 SELECT語句關鍵字的定義順序 二 SELECT語句關鍵字的執行順序 三 準備表和數據 四 準備SQL邏輯查詢測試語句 五 執行順序分析 一 SELECT語句關鍵字的定義

Mysql補充部分:SQL邏輯查詢語句執行順序

num 支持 重復數 mysql 當我 每次 列表 sha mysq 一 SELECT語句關鍵字的定義順序 SELECT DISTINCT <select_list> FROM <left_table> <join_typ

mysql第四篇--SQL邏輯查詢語句執行順序

l數據庫 分組操作 一定的 內容 isp 新建 處理 hid 表示 mysql第四篇--SQL邏輯查詢語句執行順序 一.SQL語句定義順序 SELECT DISTINCT <select_list> FROM <left_table> <jo

MySQLSQL邏輯查詢語句執行順序

最後,這篇文章是我讀《MySQL技術內幕:SQL程式設計》而總結出來的,對於書中有的東西講的比較“粗”,可能是我的水平沒有達到人家作者要求的水平,導致閱讀起來,不是很舒服,所以,這篇博文,將會非常細緻的進行總結。只有你想不到,沒有你做不到。能看懂麼?先來一段虛擬碼,首先你能看

45、SQL邏輯查詢語句執行順序

mysq 一定的 gif 行數據 查詢語句 客戶 prim 記錄 測試表 一 SELECT語句關鍵字的定義順序 SELECT DISTINCT <select_list> FROM <left_table> <join_type> J

SQL邏輯查詢語句執行順序 需要重新整理

lis highlight 虛擬表 發生 最終 數據處理 adding sql查詢 邏輯語句 一.SQL語句定義順序 1 2 3 4 5 6 7 8 9 10 SELECT DISTINCT <select_list> FROM <l

SQL邏輯查詢語句執行順序

number HERE 語句 order distinct type limit con lis SELECT語句語法順序 SELECT DISTINCT <select_list> FROM <left_table> <join_

sql邏輯查詢語句執行順序

SELECT語句關鍵字的定義順序 SELECT DISTINCT <select_list> FROM <left_table> <join_type> JOIN <right_table> ON <join_condition> W

Mysql----SQL查詢語句執行順序

SQL查詢語句執行順序如下: (7) SELECT (8) DISTINCT <select_list> (1) FROM <left_table>(3) <join_type> JOIN <right_table>

oracle查詢語句執行順序

lin oracle查詢 etc utl columns contain 處理 text lec 完整的查詢語句類似是這樣的: select ..., ROWNUM from table where <where clause> group by &

MySQL sql語句執行順序

left join left 笛卡爾積 ner 別名 join 例如 結果 detail sql語句select語句查詢順序 (7) SELECT (8) DISTINCT <select_list> (1) FROM <

關於sqlMySQL語句執行順序

sql和mysql執行順序,發現內部機制是一樣的。最大區別是在別名的引用上。  一、sql執行順序  (1) from (3) join (2) on (4) where (5) group by(開始使用select中的別名,後面的語句中都可以使用) (6) avg,s

MySQL 抓取SQL查詢語句

mysql 索引 數據表 sql慢查詢 逗哥自動化 當MySQL服務器出現異常(慢),首先要考慮是否因,SQL語句引起數據庫慢,如果情況比較緊急,我們就要立刻 SHOW FULL PROCESSLIST; 去查看,但我建議大家使用-e參數,采用非交互的方式,因為這樣可以使用grep

mysql優化必知(mysql語句執行順序

distinct 笛卡爾 技術分享 應用 一個 body where條件 img 處理 MySQL的語句執行順序 MySQL的語句一共分為11步,如下圖所標註的那樣,最先執行的總是FROM操作,最後執行的是LIMIT操作。其中每一個操作都會產生一張虛擬的表,這個虛擬的表

Mysql語句執行順序

tinc .com 上一個 取出 col 圖片 TP 需要 聚合操作 MySQL的語句執行順序 MySQL的語句一共分為11步,如下圖所標註的那樣,最先執行的總是FROM操作,最後執行的是LIMIT操作。其中每一個操作都會產生一張虛擬的表,這個虛擬的表作為一個處理的輸入,

mysql基礎架構之查詢語句執行流程

這篇筆記主要記錄mysql的基礎架構,一條查詢語句是如何執行的。 比如,在我們從student表中查詢一個id=2的資訊 select * from student where id=2; 在解釋這條語句執行流程之前,我們看看mysql的基礎架構。 圖來自極客時間的mysql實踐,該圖是描述的是M

ORACLE中查詢語句執行順及where部分條件執行順序測試 Oracle中的一些查詢語句及其執行順序 Select 語句執行順序以及如何提高Oracle 基本查詢效率

Oracle中的一些查詢語句及其執行順序 原文地址:https://www.cnblogs.com/likeju/p/5039115.html 查詢條件:1)LIKE:模糊查詢,需要藉助兩個萬用字元,%:表示0到多個字元;_:標識單個字元。2)IN(list):用來取出符合列表範圍中的資料。3)NOT I

SQL語句執行順序

sql和mysql執行順序,發現內部機制是一樣的。最大區別是在別名的引用上。  一、sql執行順序  (1)from  (3) join  (2) on  (4) where  (5)group by(開始使用select中的別名,後面的語句中都可以使用) (6) avg

Python 執行sql條件查詢語句速度很慢的解決方法

問題描述 今天寫程式碰到一個問題,程式剛開始執行的好好的,到了後面,資料庫中的檔案越來越多的時候,程式執行開始變慢,到了後來, 一條條件查詢語句,竟然要用一分鐘之久,要知道只有幾萬條資料(雖然資料內容很大) 解決方法 這個問題,困擾我好久,我之前一直在優化自