共計 15927 個字符,預計需要花費 40 分鐘才能閱讀完成。
這篇文章主要介紹“MySQL 連接查詢的方法是什么”,在日常操作中,相信很多人在 MySQL 連接查詢的方法是什么問題上存在疑惑,丸趣 TV 小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”MySQL 連接查詢的方法是什么”的疑惑有所幫助!接下來,請跟著丸趣 TV 小編一起來學習吧!
再次認識關系表
我們之前一直使用 student_info 和 student_score 兩個表來分別存儲學生的基本信息和學生的成績信息,其實合并成一張表也不是不可以,假設將兩張表合并后的新表名稱為 student_merge,那它應該長這樣:
student_merge 表
numbernamesexid_numberdepartmentmajorenrollment_timesubjectscore20180101 杜子騰男 158177199901044792 計算機學院計算機科學與工程 2018-09-01 母豬的產后護理 7820180101 杜子騰男 158177199901044792 計算機學院計算機科學與工程 2018-09-01 論薩達姆的戰爭準備 8820180102 杜琦燕女 151008199801178529 計算機學院計算機科學與工程 2018-09-01 母豬的產后護理 10020180102 杜琦燕女 151008199801178529 計算機學院計算機科學與工程 2018-09-01 論薩達姆的戰爭準備 9820180103 范統男 17156319980116959X 計算機學院軟件工程 2018-09-01 母豬的產后護理 5920180103 范統男 17156319980116959X 計算機學院軟件工程 2018-09-01 論薩達姆的戰爭準備 6120180104 史珍香女 141992199701078600 計算機學院軟件工程 2018-09-01 母豬的產后護理 5520180104 史珍香女 141992199701078600 計算機學院軟件工程 2018-09-01 論薩達姆的戰爭準備 4620180105 范劍男 181048200008156368 航天學院飛行器設計 2018-09-01NULLNULL20180106 朱逸群男 197995199801078445 航天學院電子信息 2018-09-01NULLNULL
有了這個合并后的表,我們就可以在一個查詢語句中既查詢到學生的基本信息,也查詢到學生的成績信息,比如這個查詢語句:
SELECT number, name, major, subject, score FROM student_merge;
其中查詢列表處的 name 和 major 屬于學生的基本信息,subject 和 score 屬于學生的成績信息,而 number 既屬于成績信息也屬于基本信息,我們可以在一個對 student_merge 表的查詢語句中很輕松的把這些信息都查詢出來。但是別忘了一個學生可能會有很多門學科的成績信息,也就是說每當我們想為一個學生增加一門學科的成績信息時,我們必須把他的基本信息再抄一遍,這種同一個學生的基本信息被冗余存儲會帶來下邊的問題:
問題一:浪費存儲空間。
問題二:當修改某個學生的基本信息時必須修改多處,很容易造成信息的不一致,增大維護的困難。
所以為了盡可能少的存儲冗余信息,一開始我們就把這個所謂的 student_merge 表拆分成了 student_info 和 student_score 表,但是這兩張表之間有某種關系作為紐帶,這里的某種關系指的就是兩個表都擁有的 number 列。
連接的概念
拆分之后的表的確解決了數據冗余問題,但是查詢數據卻成了一個問題。截至目前為止,在我們介紹的查詢方式中,查詢結果集只能是一個表中的一個列或者多個列,也就是說到目前為止還沒有一種可以在一條查詢語句中把某個學生的 number、name、major、subject、score 這幾個信息都查詢出來的方式。
小貼士:雖然我們前邊介紹的子查詢可以在一個查詢語句中涉及到多個表,但是整個查詢語句最終產生的結果集還是用來展示外層查詢的結果,子查詢的結果只是被當作中間結果來使用。
時代在召喚一種可以在一個查詢語句結果集中展示多個表的信息的方式,連接查詢承擔了這個艱巨的歷史使命。當然,為了故事的順利發展,我們先建立兩個簡單的表并給它們填充一點數據:
mysql CREATE TABLE t1 (m1 int, n1 char(1));
Query OK, 0 rows affected (0.02 sec)
mysql CREATE TABLE t2 (m2 int, n2 char(1));
Query OK, 0 rows affected (0.02 sec)
mysql INSERT INTO t1 VALUES(1, a), (2, b), (3, c
Query OK, 3 rows affected (0.00 sec)
Records: 3 Duplicates: 0 Warnings: 0
mysql INSERT INTO t2 VALUES(2, b), (3, c), (4, d
Query OK, 3 rows affected (0.00 sec)
Records: 3 Duplicates: 0 Warnings: 0
mysql
我們成功建立了 t1、t2 兩個表,這兩個表都有兩個列,一個是 INT 類型的,一個是 CHAR(1) 類型的,填充好數據的兩個表長這樣:
mysql SELECT * FROM t1;
+------+------+
| m1 | n1 |
+------+------+
| 1 | a |
| 2 | b |
| 3 | c |
+------+------+
3 rows in set (0.00 sec)
mysql SELECT * FROM t2;
+------+------+
| m2 | n2 |
+------+------+
| 2 | b |
| 3 | c |
| 4 | d |
+------+------+
3 rows in set (0.00 sec)
mysql
連接的本質就是把各個表中的記錄都取出來依次匹配的組合加入結果集并返回給用戶。我們把 t1 和 t2 兩個表連接起來的過程如下圖所示:
這個過程看起來就是把 t1 表的記錄和 t2 表的記錄連起來組成新的更大的記錄,所以這個查詢過程稱之為連接查詢。連接查詢的結果集中包含一個表中的每一條記錄與另一個表中的每一條記錄相互匹配的組合,像這樣的結果集就可以稱之為笛卡爾積。因為表 t1 中有 3 條記錄,表 t2 中也有 3 條記錄,所以這兩個表連接之后的笛卡爾積就有 3×3= 9 行記錄。在 MySQL 中,連接查詢的語法也很隨意,只要在 FROM 語句后邊跟多個用逗號, 隔開的表名就好了,比如我們把 t1 表和 t2 表連接起來的查詢語句可以寫成這樣:
mysql SELECT * FROM t1, t2;
+------+------+------+------+
| m1 | n1 | m2 | n2 |
+------+------+------+------+
| 1 | a | 2 | b |
| 2 | b | 2 | b |
| 3 | c | 2 | b |
| 1 | a | 3 | c |
| 2 | b | 3 | c |
| 3 | c | 3 | c |
| 1 | a | 4 | d |
| 2 | b | 4 | d |
| 3 | c | 4 | d |
+------+------+------+------+
9 rows in set (0.00 sec)
查詢列表處的 * 代表從 FROM 語句后列出的表中選取每個列,上邊的查詢語句其實和下邊這幾種寫法都是等價的:
寫法一:
SELECT t1.m1, t1.n1, t2.m2, t2.n2 FROM t1, t2;
這種寫法是將 t1、t2 表中的列名都顯式的寫出來,也就是使用了列的全限定名。
寫法二:
SELECT m1, n1, m2, n2 FROM t1, t2;
由于 t1、t2 表中的列名并不重復,所以沒有可能讓服務器懵逼的二義性,在查詢列表上直接使用列名也是可以的。
寫法三:
SELECT t1.*, t2.* FROM t1, t2;
這種寫法意思就是查詢 t1 表的全部的列,t2 表的全部的列。
連接過程簡介
如果我們樂意,我們可以連接任意數量張表,但是如果沒有任何限制條件的話,這些表連接起來產生的笛卡爾積可能是非常巨大的。比方說 3 個 100 行記錄的表連接起來產生的笛卡爾積就有 100×100×100=1000000 行數據!所以在連接的時候過濾掉特定記錄組合是有必要的,在連接查詢中的過濾條件可以分成兩種:
涉及單表的條件
這種只涉及單表的過濾條件我們之前都提到過一萬遍了,我們之前也一直稱為搜索條件,比如 t1.m1 1 是只針對 t1 表的過濾條件,t2.n2 d 是只針對 t2 表的過濾條件。
涉及兩表的條件
這種過濾條件我們之前沒見過,比如 t1.m1 = t2.m2、t1.n1 t2.n2 等,這些條件中涉及到了兩個表,我們稍后會仔細分析這種過濾條件是如何使用的哈。
下邊我們就要看一下攜帶過濾條件的連接查詢的大致執行過程了,比方說下邊這個查詢語句:
SELECT * FROM t1, t2 WHERE t1.m1 1 AND t1.m1 = t2.m2 AND t2.n2 d
在這個查詢中我們指明了這三個過濾條件:
t1.m1 1
t1.m1 = t2.m2
t2.n2 d
那么這個連接查詢的大致執行過程如下:
首先確定第一個需要查詢的表,這個表稱之為驅動表。此處假設使用 t1 作為驅動表,那么就需要到 t1 表中找滿足 t1.m1 1 的記錄,符合這個條件的 t1 表記錄如下所示:
+------+------+
| m1 | n1 |
+------+------+
| 2 | b |
| 3 | c |
+------+------+
2 rows in set (0.01 sec)
我們可以看到,t1 表中符合 t1.m1 1 的記錄有兩條。
上一步驟中從驅動表每獲取到一條記錄,都需要到 t2 表中查找匹配的記錄,所謂匹配的記錄,指的是符合過濾條件的記錄。因為是根據 t1 表中的記錄去找 t2 表中的記錄,所以 t2 表也可以被稱之為被驅動表。上一步驟從驅動表中得到了 2 條記錄,也就意味著需要查詢 2 次 t2 表。此時涉及兩個表的列的過濾條件 t1.m1 = t2.m2 就派上用場了:
所以整個連接查詢的執行最后得到的結果集就是這樣:
+------+------+------+------+
| m1 | n1 | m2 | n2 |
+------+------+------+------+
| 2 | b | 2 | b |
| 3 | c | 3 | c |
+------+------+------+------+
2 rows in set (0.00 sec)
對于從 t1 表種查詢得到的第一條記錄,也就是當 t1.m1 = 2, t1.n1 = b 時,過濾條件 t1.m1 = t2.m2 就相當于 t2.m2 = 2,所以此時 t2 表相當于有了 t2.m2 = 2、t2.n2 d 這兩個過濾條件,然后到 t2 表中執行單表查詢,將得到的記錄和從 t1 表中查詢得到的第一條記錄相組合得到下邊的結果:
+------+------+------+------+
| m1 | n1 | m2 | n2 |
+------+------+------+------+
| 2 | b | 2 | b |
+------+------+------+------+
對于從 t1 表種查詢得到的第二條記錄,也就是當 t1.m1 = 3, t1.n1 = c 時,過濾條件 t1.m1 = t2.m2 就相當于 t2.m2 = 3,所以此時 t2 表相當于有了 t2.m2 = 3、t2.n2 d 這兩個過濾條件,然后到 t2 表中執行單表查詢,將得到的記錄和從 t1 表中查詢得到的第二條記錄相組合得到下邊的結果:
+------+------+------+------+
| m1 | n1 | m2 | n2 |
+------+------+------+------+
| 3 | c | 3 | c |
+------+------+------+------+
從上邊兩個步驟可以看出來,我們上邊嘮叨的這個兩表連接查詢共需要查詢 1 次 t1 表,2 次 t2 表。當然這是在特定的過濾條件下的結果,如果我們把 t1.m1 1 這個條件去掉,那么從 t1 表中查出的記錄就有 3 條,就需要查詢 3 次 t2 表了。也就是說在兩表連接查詢中,驅動表只需要查詢一次,被驅動表可能會被查詢多次。
內連接和外連接
了解了連接查詢的執行過程之后,視角再回到我們的 student_info 表和 student_score 表?,F在我們想在一個查詢語句中既查詢到學生的基本信息,也查詢到學生的成績信息,就需要進行兩表連接了。連接過程就是從 student_info 表中取出記錄,在 student_score 表中查找 number 值相同的成績記錄,所以過濾條件就是 student_info.number = student_score.number,整個查詢語句就是這樣:
mysql SELECT student_info.number, name, major, subject, score FROM student_info, student_score WHERE student_info.number = student_score.number;
+----------+-----------+--------------------------+-----------------------------+-------+
| number | name | major | subject | score |
+----------+-----------+--------------------------+-----------------------------+-------+
| 20180101 | 杜子騰 | 計算機科學與工程 | 母豬的產后護理 | 78 |
| 20180101 | 杜子騰 | 計算機科學與工程 | 論薩達姆的戰爭準備 | 88 |
| 20180102 | 杜琦燕 | 計算機科學與工程 | 母豬的產后護理 | 100 |
| 20180102 | 杜琦燕 | 計算機科學與工程 | 論薩達姆的戰爭準備 | 98 |
| 20180103 | 范統 | 軟件工程 | 母豬的產后護理 | 59 |
| 20180103 | 范統 | 軟件工程 | 論薩達姆的戰爭準備 | 61 |
| 20180104 | 史珍香 | 軟件工程 | 母豬的產后護理 | 55 |
| 20180104 | 史珍香 | 軟件工程 | 論薩達姆的戰爭準備 | 46 |
+----------+-----------+--------------------------+-----------------------------+-------+
8 rows in set (0.00 sec)
mysql
小貼士:student_info 表和 student_score 表都有 number 列,不過我們在上述查詢語句的查詢列表中只放置了 student_info 表的 number 列,這是因為我們的過濾條件是 student_info.number = student_score.number,從兩個表中取出的記錄的 number 列都相同,所以只需要放置一個表中的 number 列到查詢列表即可,也就是說我們把 student_score.number 放到查詢列表處也是可以滴~
從上述查詢結果中我們可以看到,各個同學對應的各科成績就都被查出來了,可是有個問題,范劍和朱逸群同學,也就是學號為 20180105 和 20180106 的同學因為某些原因沒有參加考試,所以在 studnet_score 表中沒有對應的成績記錄。那如果老師想查看所有同學的考試成績,即使是缺考的同學也應該展示出來,但是到目前為止我們介紹的連接查詢是無法完成這樣的需求的。我們稍微思考一下這個需求,其本質是想:驅動表中的記錄即使在被驅動表中沒有匹配的記錄,也仍然需要加入到結果集。為了解決這個問題,就有了內連接和外連接的概念:
對于內連接的兩個表,驅動表中的記錄在被驅動表中找不到匹配的記錄,該記錄不會加入到最后的結果集,我們上邊提到的連接都是所謂的內連接。
對于外連接的兩個表,驅動表中的記錄即使在被驅動表中沒有匹配的記錄,也仍然需要加入到結果集。
在 MySQL 中,根據選取驅動表的不同,外連接仍然可以細分為 2 種:
左外連接
選取左側的表為驅動表。
右外連接
選取右側的表為驅動表。
可是這樣仍然存在問題,即使對于外連接來說,有時候我們也并不想把驅動表的全部記錄都加入到最后的結果集。這就犯難了,有時候匹配失敗要加入結果集,有時候又不要加入結果集,這咋辦,有點兒愁啊。。。噫,把過濾條件分為兩種不就解決了這個問題了么,所以放在不同地方的過濾條件是有不同語義的:
WHERE 子句中的過濾條件
WHERE 子句中的過濾條件就是我們平時見的那種,不論是內連接還是外連接,凡是不符合 WHERE 子句中的過濾條件的記錄都不會被加入最后的結果集。
ON 子句中的過濾條件
對于外連接的驅動表的記錄來說,如果無法在被驅動表中找到匹配 ON 子句中的過濾條件的記錄,那么該記錄仍然會被加入到結果集中,對應的被驅動表記錄的各個字段使用 NULL 值填充。
需要注意的是,這個 ON 子句是專門為外連接驅動表中的記錄在被驅動表找不到匹配記錄時應不應該把該記錄加入結果集這個場景下提出的,所以如果把 ON 子句放到內連接中,MySQL 會把它和 WHERE 子句一樣對待,也就是說:內連接中的 WHERE 子句和 ON 子句是等價的。
一般情況下,我們都把只涉及單表的過濾條件放到 WHERE 子句中,把涉及兩表的過濾條件都放到 ON 子句中,我們也一般把放到 ON 子句中的過濾條件也稱之為連接條件。
小貼士:左外連接和右外連接簡稱左連接和右連接,所以下邊提到的左外連接和右外連接中的 ` 外 ` 字都用括號擴起來,以表示這個字兒可有可無。
左(外)連接的語法
左(外)連接的語法還是挺簡單的,比如我們要把 t1 表和 t2 表進行左外連接查詢可以這么寫:
SELECT * FROM t1 LEFT [OUTER] JOIN t2 ON 連接條件 [WHERE 普通過濾條件];
其中中括號里的 OUTER 單詞是可以省略的。對于 LEFT JOIN 類型的連接來說,我們把放在左邊的表稱之為外表或者驅動表,右邊的表稱之為內表或者被驅動表。所以上述例子中 t1 就是外表或者驅動表,t2 就是內表或者被驅動表。需要注意的是,對于左(外)連接和右(外)連接來說,必須使用 ON 子句來指出連接條件。了解了左(外)連接的基本語法之后,再次回到我們上邊那個現實問題中來,看看怎樣寫查詢語句才能把所有的學生的成績信息都查詢出來,即使是缺考的考生也應該被放到結果集中:
mysql SELECT student_info.number, name, major, subject, score FROM student_info LEFT JOIN student_score ON student_info.number = student_score.number;
+----------+-----------+--------------------------+-----------------------------+-------+
| number | name | major | subject | score |
+----------+-----------+--------------------------+-----------------------------+-------+
| 20180101 | 杜子騰 | 計算機科學與工程 | 母豬的產后護理 | 78 |
| 20180101 | 杜子騰 | 計算機科學與工程 | 論薩達姆的戰爭準備 | 88 |
| 20180102 | 杜琦燕 | 計算機科學與工程 | 母豬的產后護理 | 100 |
| 20180102 | 杜琦燕 | 計算機科學與工程 | 論薩達姆的戰爭準備 | 98 |
| 20180103 | 范統 | 軟件工程 | 母豬的產后護理 | 59 |
| 20180103 | 范統 | 軟件工程 | 論薩達姆的戰爭準備 | 61 |
| 20180104 | 史珍香 | 軟件工程 | 母豬的產后護理 | 55 |
| 20180104 | 史珍香 | 軟件工程 | 論薩達姆的戰爭準備 | 46 |
| 20180105 | 范劍 | 飛行器設計 | NULL | NULL |
| 20180106 | 朱逸群 | 電子信息 | NULL | NULL |
+----------+-----------+--------------------------+-----------------------------+-------+
10 rows in set (0.00 sec)
mysql
從結果集中可以看出來,雖然范劍和朱逸群并沒有對應的成績記錄,但是由于采用的是連接類型為左(外)連接,所以仍然把它放到了結果集中,只不過在對應的成績記錄的各列使用 NULL 值填充而已。
右(外)連接的語法
右(外)連接和左(外)連接的原理是一樣一樣的,語法也只是把 LEFT 換成 RIGHT 而已:
SELECT * FROM t1 RIGHT [OUTER] JOIN t2 ON 連接條件 [WHERE 普通過濾條件];
只不過驅動表是右邊的表,被驅動表是左邊的表,具體就不嘮叨了。
內連接的語法
內連接和外連接的根本區別就是在驅動表中的記錄不符合 ON 子句中的連接條件時不會把該記錄加入到最后的結果集,我們最開始嘮叨的那些連接查詢的類型都是內連接。不過之前僅僅提到了一種最簡單的內連接語法,就是直接把需要連接的多個表都放到 FROM 子句后邊。其實針對內連接,MySQL 提供了好多不同的語法,我們以 t1 和 t2 表為例瞅瞅:
SELECT * FROM t1 [INNER | CROSS] JOIN t2 [ON 連接條件] [WHERE 普通過濾條件];
也就是說在 MySQL 中,下邊這幾種內連接的寫法都是等價的:
SELECT * FROM t1 JOIN t2;
SELECT * FROM t1 INNER JOIN t2;
SELECT * FROM t1 CROSS JOIN t2;
上邊的這些寫法和直接把需要連接的表名放到 FROM 語句之后,用逗號, 分隔開的寫法是等價的:
SELECT * FROM t1, t2;
現在我們雖然介紹了很多種內連接的書寫方式,不過熟悉一種就好了,這里我們推薦 INNER JOIN 的形式書寫內連接(因為 INNER JOIN 語義很明確嘛,可以和 LEFT JOIN 和 RIGHT JOIN 很輕松的區分開)。這里需要注意的是,由于在內連接中 ON 子句和 WHERE 子句是等價的,所以內連接中不要求強制寫明 ON 子句。
我們前邊說過,連接的本質就是把各個連接表中的記錄都取出來依次匹配的組合加入結果集并返回給用戶。不論哪個表作為驅動表,兩表連接產生的笛卡爾積肯定是一樣的。而對于內連接來說,由于凡是不符合 ON 子句或 WHERE 子句中的條件的記錄都會被過濾掉,其實也就相當于從兩表連接的笛卡爾積中把不符合過濾條件的記錄給踢出去,所以對于內連接來說,驅動表和被驅動表是可以互換的,并不會影響最后的查詢結果。但是對于外連接來說,由于驅動表中的記錄即使在被驅動表中找不到符合 ON 子句連接條件的記錄也會被加入結果集,所以此時驅動表和被驅動表的關系就很重要了,也就是說左外連接和右外連接的驅動表和被驅動表不能輕易互換。
小結
上邊說了很多,給大家的感覺不是很直觀,我們直接把表 t1 和 t2 的三種連接方式寫在一起,這樣大家理解起來就很 easy 了:
mysql SELECT * FROM t1 INNER JOIN t2 ON t1.m1 = t2.m2;
+------+------+------+------+
| m1 | n1 | m2 | n2 |
+------+------+------+------+
| 2 | b | 2 | b |
| 3 | c | 3 | c |
+------+------+------+------+
2 rows in set (0.00 sec)
mysql SELECT * FROM t1 LEFT JOIN t2 ON t1.m1 = t2.m2;
+------+------+------+------+
| m1 | n1 | m2 | n2 |
+------+------+------+------+
| 2 | b | 2 | b |
| 3 | c | 3 | c |
| 1 | a | NULL | NULL |
+------+------+------+------+
3 rows in set (0.00 sec)
mysql SELECT * FROM t1 RIGHT JOIN t2 ON t1.m1 = t2.m2;
+------+------+------+------+
| m1 | n1 | m2 | n2 |
+------+------+------+------+
| 2 | b | 2 | b |
| 3 | c | 3 | c |
| NULL | NULL | 4 | d |
+------+------+------+------+
3 rows in set (0.00 sec)
連接查詢產生的結果集就好像把散布到兩個表中的信息被重新粘貼到了一個表,這個粘貼后的結果集可以方便我們分析數據,就不用老是兩個表對照的看了。
多表連接
上邊說過,如果我們樂意的話可以連接任意數量的表,我們再來創建一個簡單的 t3 表:
mysql CREATE TABLE t3 (m3 int, n3 char(1));
ERROR 1050 (42S01): Table t3 already exists
mysql INSERT INTO t3 VALUES(3, c), (4, d), (5, e
Query OK, 3 rows affected (0.01 sec)
Records: 3 Duplicates: 0 Warnings: 0
mysql
與 t1 和 t2 表的結構一樣,也是一個 INT 列,一個 CHAR(1) 列,現在我們看一下把這 3 個表連起來的樣子:
mysql SELECT * FROM t1 INNER JOIN t2 INNER JOIN t3 WHERE t1.m1 = t2.m2 AND t1.m1 = t3.m3;
+------+------+------+------+------+------+
| m1 | n1 | m2 | n2 | m3 | n3 |
+------+------+------+------+------+------+
| 3 | c | 3 | c | 3 | c |
+------+------+------+------+------+------+
1 row in set (0.00 sec)
mysql
其實上邊的查詢語句也可以寫成這樣,用哪個取決于你的心情:
SELECT * FROM t1 INNER JOIN t2 ON t1.m1 = t2.m2 INNER JOIN t3 ON t1.m1 = t3.m3;
這個查詢的執行過程用偽代碼表示一下就是這樣:
for each row in t1 {
for each row in t2 which satisfies t1.m1 = t2.m2 {
for each row in t3 which satisfies t1.m1 = t3.m3 {
send to client;
}
}
}
其實不管是多少個表的連接,本質上就是各個表的記錄在符合過濾條件下的自由組合。
表的別名
我們前邊曾經為列命名過別名,比如說這樣:
mysql SELECT number AS xuehao FROM student_info;
+----------+
| xuehao |
+----------+
| 20180104 |
| 20180102 |
| 20180101 |
| 20180103 |
| 20180105 |
| 20180106 |
+----------+
6 rows in set (0.00 sec)
mysql
我們可以把列的別名用在 ORDER BY、GROUP BY 等子句上,比如這樣:
mysql SELECT number AS xuehao FROM student_info ORDER BY xuehao DESC;
+----------+
| xuehao |
+----------+
| 20180106 |
| 20180105 |
| 20180104 |
| 20180103 |
| 20180102 |
| 20180101 |
+----------+
6 rows in set (0.00 sec)
mysql
與列的別名類似,我們也可以為表來定義別名,格式與定義列的別名一致,都是用空白字符或者 AS 隔開,這個在表名特別長的情況下可以讓語句表達更清晰一些,比如這樣:
mysql SELECT s1.number, s1.name, s1.major, s2.subject, s2.score FROM student_info AS s1 INNER JOIN student_score AS s2 WHERE s1.number = s2.number;
+----------+-----------+--------------------------+-----------------------------+-------+
| number | name | major | subject | score |
+----------+-----------+--------------------------+-----------------------------+-------+
| 20180101 | 杜子騰 | 計算機科學與工程 | 母豬的產后護理 | 78 |
| 20180101 | 杜子騰 | 計算機科學與工程 | 論薩達姆的戰爭準備 | 88 |
| 20180102 | 杜琦燕 | 計算機科學與工程 | 母豬的產后護理 | 100 |
| 20180102 | 杜琦燕 | 計算機科學與工程 | 論薩達姆的戰爭準備 | 98 |
| 20180103 | 范統 | 軟件工程 | 母豬的產后護理 | 59 |
| 20180103 | 范統 | 軟件工程 | 論薩達姆的戰爭準備 | 61 |
| 20180104 | 史珍香 | 軟件工程 | 母豬的產后護理 | 55 |
| 20180104 | 史珍香 | 軟件工程 | 論薩達姆的戰爭準備 | 46 |
+----------+-----------+--------------------------+-----------------------------+-------+
8 rows in set (0.00 sec)
mysql
這個例子中,我們在 FROM 子句中給 student_info 定義了一個別名 s1,student_score 定義了一個別名 s2,那么在整個查詢語句的其他地方就可以引用這個別名來替代該表本身的名字了。
自連接
我們上邊說的都是多個不同的表之間的連接,其實同一個表也可以進行連接。比方說我們可以對兩個 t1 表來生成笛卡爾積,就像這樣:
mysql SELECT * FROM t1, t1;
ERROR 1066 (42000): Not unique table/alias: t1
mysql
咦,報了個錯,這是因為設計 MySQL 的大叔不允許 FROM 子句中出現相同的表名。我們這里需要的是兩張一模一樣的 t1 表進行連接,為了把兩個一樣的表區分一下,需要為表定義別名。比如這樣:
mysql SELECT * FROM t1 AS table1, t1 AS table2;
+------+------+------+------+
| m1 | n1 | m1 | n1 |
+------+------+------+------+
| 1 | a | 1 | a |
| 2 | b | 1 | a |
| 3 | c | 1 | a |
| 1 | a | 2 | b |
| 2 | b | 2 | b |
| 3 | c | 2 | b |
| 1 | a | 3 | c |
| 2 | b | 3 | c |
| 3 | c | 3 | c |
+------+------+------+------+
9 rows in set (0.00 sec)
mysql
這里相當于我們為 t1 表定義了兩個副本,一個是 table1,另一個是 table2,這里的連接過程就不贅述了,大家把它們認為是不同的表就好了。由于被連接的表其實是源自同一個表,所以這種連接也稱為自連接。我們看一下這個自連接的現實意義,比方說我們想查看與 史珍香 相同專業的學生有哪些,可以這么寫:
mysql SELECT s2.number, s2.name, s2.major FROM student_info AS s1 INNER JOIN student_info AS s2 WHERE s1.major = s2.major AND s1.name = 史珍香 ;
+----------+-----------+--------------+
| number | name | major |
+----------+-----------+--------------+
| 20180103 | 范統 | 軟件工程 |
| 20180104 | 史珍香 | 軟件工程 |
+----------+-----------+--------------+
2 rows in set (0.01 sec)
mysql
s1、s2 都可以看作是 student_info 表的一份副本,我們可以這樣理解這個查詢:
根據 s1.name = 史珍香 搜索條件過濾 s1 表,可以得到該同學的基本信息:
+----------+-----------+------+--------------------+-----------------+--------------+-----------------+
| number | name | sex | id_number | department | major | enrollment_time |
+----------+-----------+------+--------------------+-----------------+--------------+-----------------+
| 20180104 | 史珍香 | 女 | 141992199701078600 | 計算機學院 | 軟件工程 | 2018-09-01 |
+----------+-----------+------+--------------------+-----------------+--------------+-----------------+
因為通過查詢 s1 表,得到了 史珍香 所在的專業其實是 軟件工程,接下來就應該查詢 s2 表了,查詢 s2 表的時候的過濾條件 s1.major = s2.major 就相當于 s2.major = 軟件工程,于是查詢到 2 條記錄:
+----------+-----------+------+--------------------+-----------------+--------------+-----------------+
| number | name | sex | id_number | department | major | enrollment_time |
+----------+-----------+------+--------------------+-----------------+--------------+-----------------+
| 20180103 | 范統 | 男 | 17156319980116959X | 計算機學院 | 軟件工程 | 2018-09-01 |
| 20180104 | 史珍香 | 女 | 141992199701078600 | 計算機學院 | 軟件工程 | 2018-09-01 |
+----------+-----------+------+--------------------+-----------------+--------------+-----------------+
而我們只需要 s2 表的 number、name、major 這 3 個列的數據,所以最終的結果就長這樣:
+----------+-----------+--------------+
| number | name | major |
+----------+-----------+--------------+
| 20180103 | 范統 | 軟件工程 |
| 20180104 | 史珍香 | 軟件工程 |
+----------+-----------+--------------+
連接查詢與子查詢的轉換
有的查詢需求既可以使用連接查詢解決,也可以使用子查詢解決,比如
SELECT * FROM student_score WHERE number IN (SELECT number FROM student_info WHERE major = 計算機科學與工程
這個子查詢就可以被替換:
SELECT s2.* FROM student_info AS s1 INNER JOIN student_score AS s2 WHERE s1.number = s2.number AND s1.major = 計算機科學與工程
大家在實際使用時可以按照自己的習慣來書寫查詢語句。
小貼士:MySQL 服務器在內部可能將子查詢轉換為連接查詢來處理,當然也可能用別的方式來處理,不過對于我們剛入門的小白來說,這些都不重要,知道這個語句會把哪些信息查出來就好了!
到此,關于“MySQL 連接查詢的方法是什么”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注丸趣 TV 網站,丸趣 TV 小編會繼續努力為大家帶來更多實用的文章!