天天看點

一條SQL語句的“一生”

SQL語言相信大家都不陌生,從本質上來說,它是一種結構化查詢語言,是用來資料庫之間的通信的程式設計語言。作為一名Java程式員,我們從Java角度來看,SQL語言相當于Java接口,而資料庫是實作這個接口的實作類,SQL語句則是實作類的方法!!。從這裡我們就可以了解了,每個資料庫都有着自己獨特的規則,但大體上是遵循SQL标準。

SQL 語句有一個讓大部分人都感到困惑的地方,就是我寫的 SQL 語句的跟我預想要的結果不一樣。在這裡,我們就以 Mysql 資料庫為例,對一條 SQL 語句的執行順序進行分析。

接下來再走一步,讓我們看看一條 SQL 語句的前世今生。

首先看一下示例語句

一條SQL語句的“一生”

它的執行順序是這樣的

一條SQL語句的“一生”

準備資料

我們會先準備一些資料,即建立 classes、student 表,并插入測試資料, SQL語句如下:

一條SQL語句的“一生”
一條SQL語句的“一生”

OK,有了資料之後,我們就可以來看看 SQL 語句在 MySQL 中執行過程了,SQL 語句如下:

一條SQL語句的“一生”

SQL執行之旅

可能你現在還對 Mysql 語句的執行順序一知半解,沒關系,下來我将按 SQL 執行的順序詳細介紹每個關鍵字的作用,以及注意的地方。

1、FROM:首先,是從 From 開始的,對FROM子句中的前兩個表執行笛卡爾積(交叉聯接),生成虛拟表VT1。

一條SQL語句的“一生”

2、ON:對VT1應用ON篩選器,隻有那些使為真才被插入到VT2。ON不能單獨,在這裡你可以把ON了解為WHERE。

一條SQL語句的“一生”

3、JOIN:如果指定了OUTER JOIN(相對于CROSS JOIN或INNER JOIN),保留表(主表)中不符合ON條件比對的行将作為外部行添加到VT2,生成VT3。如果FROM子句超過兩個表,上一個聯接生成的結果表會和下一個表重複執行步驟1到步驟3,直到處理完所有的表的關聯。

一條SQL語句的“一生”

4、WHERE:對VT3應用WHERE篩選器,隻有為true的行才插入VT4。

一條SQL語句的“一生”

5、GROUP BY:按GROUP BY子句中的列清單對VT4中的行進行分組,生成VT5。

一條SQL語句的“一生”

在這裡會有一個奇怪的現象,MySQL執行順序GROUP BY -> HAVING -> SELECT,從順序看SELECL在GROUP BY之後,GROUP BY 應該不可以使用SELECT字段别名,但是在GROUP BY卻可以使用SELECT字段别名,主要原因MySQL擴充了标準SQL,允許GROUP BY子句使用的SELECT子句中的别名以及和非清單表達式等标準, 并認為語句是有效的。從MySQL 5.7.5開始,預設SQL mode模式包括 ONLY_FULL_GROUP_BY。(在5.7.5之前,MySQL不檢測功能依賴性,ONLY_FULL_GROUP_BY預設情況下不啟用。

6、HAVING :對VT5應用HAVING篩選器,隻有為true的組插入到VT6。

一條SQL語句的“一生”

HAVING同GROUP BY一樣,MySQL拓展SQL标準以允許HAVING可以使用别名和非清單表達式。

7、SELECT:将VT6每一組資料執行select xx,有幾組就執行幾次,産生VT7。

一條SQL語句的“一生”

這裡有一點要注意,當SQL mode 模式ONLY_FULL_GROUP_BY不開啟,不會強制SELECT指定的字段必須屬于GROUP BY後的條件。若符合條件的字段有多個,則隻顯示第一次出現的字段。雖然這種查詢在文法上通過了,但結果并沒有什麼意義,因為其他字段并非需要的準确值。是以最好SELECT語句指定的字段必須是“分組依據字段”。

8、ORDER BY:将VT7中的行按ORDER BY子句中的列清單順序,ORDER BY隻能選擇SELECT的字段

一條SQL語句的“一生”

9、LIMIT:從VT7的開始處選擇指定數量或比例的行,生成表VT8,并傳回給調用者。

一條SQL語句的“一生”

OK,到這裡就執行結束了。我們可以發現,SQL 語句的文法順序和執行順序并不一緻,如果你已經可以清醒知道它們之間差異,你就可以看出為什麼以前寫的SQL總是和我們預想的不一緻。你看,哪怕隻有一條小小的 SQL 語句都有這麼多門道,隻有不斷專研探究,我們才可以真正掌握這一門技術。

這裡多提一下,在SQL文法有幾點要特别注意,SELECT雖然在GROUP BY和HAVING 之後,但是如果SQL mode模式 ONLY_FULL_GROUP_BY不開啟,GROUP BY和HAVING是允許使用SELECT的字段,而且也不會強制SELECT指定的字段必須屬于GROUP BY後的條件。至此SQL的解析之旅就結束了,最後用一張圖總結一下今天的内容:

一條SQL語句的“一生”

最後給大家分享我寫的SQL兩件套:《SQL基礎知識第二版》和《SQL進階知識第二版》的PDF電子版。裡面有各個文法的解釋、大量的執行個體講解和批注等等,非常通俗易懂,友善大家跟着一起來實操。

有需要的讀者可以下載下傳學習,在下面的公衆号「資料前線」(非本号)背景回複關鍵字:SQL,就行

資料前線

背景回複關鍵字:1024,擷取一份精心整理的技術幹貨
背景回複關鍵字:進群,帶你進入高手如雲的交流群。