SQL在执行JOIN ON时,到底发生了什么?
點擊關注上方“SQL數據庫開發”,
設為“置頂或星標”,第一時間送達干貨
對于一些SQL初學者,寫一個簡單的單表查詢那是信手拈來。
(文末準備送幾本技術書籍給小伙伴們~)
但是遇到寫多表關聯查詢可能就懵逼了:為什么會有多表查詢這種“怪物”?要怎么寫?為什么要這樣為難我?這是誰發明的?
進而可能會引申出人生的終極哲學問題:我是誰?我在哪?我在做什么?
有點扯遠了,但確實能夠體會到一些初學者,對多表關聯查詢的困擾。今天我們就給大家講解多表關聯查詢到底是怎么一回事。
大家都知道,多表關聯查詢的關鍵字是JOIN...ON,如果只關心怎么使用,可以移步《SQL基礎知識V2——JOIN連接》。
本文主要講解JOIN ON在數據庫中是怎么執行的。
測試環境
SQL Server 2017
測試樣表
我們新建兩張測試表Customers和Orders,表結構如下:
表Customers
表Orders
要求:查詢每個客戶的訂單數量
我們先直接寫出查詢語句:
SELECT?a.CustomerName,Count(OrderID) Nums FROM?Customers a LEFT?JOIN?Orders b?ON?a.CustomerID=b.CustomerID GROUP?BY?a.CustomerName結果如下:
問:這個結果是怎么來的呢?
要搞清楚這個結果是怎么來的,我們需要先知道一個概念:笛卡爾積。
1、執行笛卡爾積(交叉聯接)
什么是笛卡爾積?
笛卡爾乘積是指在數學中,兩個集合X和Y的笛卡爾積,表示為X×Y,第一個對象是X的成員而第二個對象是Y的所有可能有序對的其中一個成員。
具體如下圖:
而我們在進行SQL的表關聯時,JOIN的第一步就是生成笛卡爾積。我們上面的代碼
...?Customers?a?LEFT?JOIN??Orders?b?...
最開始是在數據庫中生成了一張笛卡爾積的虛表T1,T1里面的數量正是兩個表(Customers和Orders)數量的乘積9條(3 × 3),我們可以使用如下代碼獲得笛卡爾積:
SELECT? B.CustomerID, B.CustomerName, A.OrderID, A.CustomerID FROM?Orders A CROSS?JOIN?Customers B查詢出來的數據如下:
虛表T1
2、執行過濾篩選
當JOIN將兩個表生成笛卡爾積的虛表T1之后,隨后的ON開始執行篩選功能,ON后面的條件就是指符合條件的返回結果TRUE,不符合條件的返回結果FALSE,以及未知情況UNKNOWN。
在繼續講解前我們需要先普及一下三值邏輯的概念
三值邏輯就是我們上面說到的ON返回的三個結果:TRUE,FALSE和UNKNOWN。
大多數的編程語言中返回的結果要么是TRUE,要么就是FALSE。而SQL中的UNKONWN通常與NULL值出現有關。
以下情況都會返回UNKNOWN:
NULL>21
NULL=NULL
X+NULL>Y
NULL代表一種缺失值,當把一個缺失值與其他任意值進行比較時,結果始終為UNKNOWN。
而我們上面的代碼中的ON的條件是這樣寫的:
...?a.CustomerID=b.CustomerID?...
意思就是取a(表Customers的別名)和b(表Orders的別名)中CustomerID相等的結果。根據這個篩選條件,虛表T1中可以生成相應邏輯值,如下圖:
ON篩選的邏輯結果表
從上面我們可以看到完全滿足條件(Logic Value的值為TRUE)的只有兩條記錄,數據庫會將這些結果插入到虛表T2,進行下一步的操作準備。
虛表T2
3、添加外部行
這一步只在外聯接(OUT JOIN)中才會發生。對于外聯接,通過為其指定一種聯接方式(LEFT,RIGHT或FULL),就把一個或兩個輸入表標記為保留表。
把表標記為保留表,即表示希望返回該表的所有行,即使ON過濾了一些行。
左連接(LEFT OUT JOIN)是把左邊的表作為保留表,右連接(RIGHT OUT JOIN)是把右邊的表作為保留表,全連接(FULL OUT JOIN)則是把兩個表都作為保留表。(我們在書寫時,通常會省略掉OUT)
在執行完ON的篩選后,我們根據寫法來添加這些保留表中記錄。
我們上面的代碼使用的是LEFT JOIN,所以我們需要將左表(注:LEFT JOIN 左邊的表)Customers表作為保留表。
在ON篩選完后,我們發現Customers表中CustomerID為1的沒有在T2中,我們需要將這條記錄的相關信息添加到T2中生成虛表T3,并且將Order表中的所有數據置為NULL,因為他們(指表Orders中的兩列)不屬于保留表,不是我們需要保留的數據。這樣匯總后虛表T3中的數據如下:
虛表T3
這樣當我們再對表Orders中的OrderID計數時,CustomerID為1的客戶因為沒有訂單,返回的結果將為0,而CustomersID為2,3的客戶都有一個訂單,返回的結果將為1。
至此整個表關聯環節就執行完成了。
參考文獻
《Microsoft SQL Server 2008技術內幕:T-SQL查詢》
以上就是JOIN在數據庫中執行的相關內容,如有不明白的地方,歡迎在底下留言。
下面是福利環節~
總結
以上是生活随笔為你收集整理的SQL在执行JOIN ON时,到底发生了什么?的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: LCD显示屏和OLED显示屏的区别
- 下一篇: 丛书【数据库面试笔试宝典】已在京东、淘宝