新聞中心
概念
因?yàn)槲覀兪褂玫氖顷P(guān)系型數(shù)據(jù)庫,每張表表示的都是獨(dú)立的單元(對象),而該單元(對象)所涉及到的其他信息通常都存儲在其他表中,例如:

成都創(chuàng)新互聯(lián)公司是一家專業(yè)提供珙縣企業(yè)網(wǎng)站建設(shè),專注與成都網(wǎng)站制作、成都網(wǎng)站設(shè)計(jì)、H5網(wǎng)站設(shè)計(jì)、小程序制作等業(yè)務(wù)。10年已為珙縣眾多企業(yè)、政府機(jī)構(gòu)等服務(wù)。創(chuàng)新互聯(lián)專業(yè)網(wǎng)站建設(shè)公司優(yōu)惠進(jìn)行中。
MariaDB [world]> DESC city;
+-------------+----------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------+----------+------+-----+---------+----------------+
| ID | int(11) | NO | PRI | NULL | auto_increment |
| Name | char(35) | NO | | | |
| CountryCode | char(3) | NO | MUL | | |
| District | char(20) | NO | | | |
| Population | int(11) | NO | | 0 | |
+-------------+----------+------+-----+---------+----------------+
5 rows in set (0.61 sec)
MariaDB [world]> DESC countrylanguage;
+-------------+---------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------------+---------------+------+-----+---------+-------+
| CountryCode | char(3) | NO | PRI | | |
| Language | char(30) | NO | PRI | | |
| IsOfficial | enum('T','F') | NO | | F | |
| Percentage | float(4,1) | NO | | 0.0 | |
+-------------+---------------+------+-----+---------+-------+
4 rows in set (0.06 sec)
比如其上兩張表,我們想知道某一城市所使用的語言,就可以分為兩個步驟:
1.在City表中查詢該城市的CountryCode。
2.使用查詢到的這個CountryCode在CountryLanguage表中查詢該國家所使用的語言。
雖然,可以分兩步完成,但是,需要兩次查詢和兩次傳輸,在帶寬和性能的對比下,我們更希望讓Mysql(MariaDB)來幫助我們完成這件事不是嗎?
連接(JOIN):也叫連結(jié),是指將兩張表按照一定規(guī)則連成一張表,將兩張表中不同的數(shù)據(jù)(行)連成一行來看待。
又可以將連接分為如下幾類:
-
內(nèi)連接
-
外連接
-
-
左外連接
-
右外連接
-
-
交叉連接
在連接查詢中,一個列可能出現(xiàn)在多張表中,為了避免引起歧義,通常在列名前面加上表名或表別名作為前綴(例:s.sid、x.sid)—使用表別名作為前綴,可以使得SQL代碼較短,使用的內(nèi)存更少(例:stu s,xuanke as x)。
內(nèi)連接
內(nèi)連接語法如下:
SELECT tb1_name.column,tb2_name.column FROM tb1 INNER JOIN tb2 ON 約束條件;
SELECT tb1_name.column,tb2_name.column FROM tb1,tb2 WHERE 約束條件;
查詢每一個城市可能使用的語言有哪些:
MariaDB [world]> SELECT Name,District,Language FROM city,countrylanguage WHERE city.CountryCode = countrylanguage.CountryCode LIMIT 10;
+----------+----------+------------+
| Name | District | Language |
+----------+----------+------------+
| Kabul | Kabol | Balochi |
| Kabul | Kabol | Dari |
| Kabul | Kabol | Pashto |
| Kabul | Kabol | Turkmenian |
| Kabul | Kabol | Uzbek |
| Qandahar | Qandahar | Balochi |
| Qandahar | Qandahar | Dari |
| Qandahar | Qandahar | Pashto |
| Qandahar | Qandahar | Turkmenian |
| Qandahar | Qandahar | Uzbek |
+----------+----------+------------+
10 rows in set (0.00 sec)
內(nèi)連接是怎樣工作的
我們來看一下,這些數(shù)據(jù)是怎么連接起來的,具體可以看如下這張圖(放大看):
所以所謂內(nèi)連接,就是僅將多表中符合條件的行進(jìn)行連接且返回結(jié)果。
比如這樣,就將三張表連接了起來:
MariaDB [world]> SELECT * FROM city INNER JOIN countrylanguage INNER JOIN country ON city.CountryCode = countrylanguage.CountryCode AND city.CountryCode = country.Code WHERE city.Name='Kabul'\G;
*************************** 1. row ***************************
ID: 1
Name: Kabul
CountryCode: AFG
District: Kabol
Population: 1780000
CountryCode: AFG
Language: Balochi
IsOfficial: F
Percentage: 0.9
Code: AFG
Name: Afghanistan
Continent: Asia
Region: Southern and Central Asia
SurfaceArea: 652090.00
IndepYear: 1919
Population: 22720000
LifeExpectancy: 45.9
GNP: 5976.00
GNPOld: NULL
LocalName: Afganistan/Afqanestan
GovernmentForm: Islamic Emirate
HeadOfState: Mohammad Omar
Capital: 1
Code2: AF
....僅截取了第一條記錄
5 rows in set (0.01 sec)
這里比較推薦SQL的標(biāo)準(zhǔn)寫法,也就是如下格式:
SELECT tb1_name.column,tb2_name.column FROM tb1 INNER JOIN tb2 ON 約束條件;
為什么呢?因?yàn)樵贠N子句后還可以跟WHERE子句多連接出來的表進(jìn)行過濾呀,且此語法結(jié)構(gòu)更清晰不是嗎?
外連接
使用內(nèi)連接會將多表中符合條件的行連接到一起,而不符合條件的行則忽略,而外連接則會將一些不符合條件的行也輸出出來。
例如,我們有如下數(shù)據(jù):
MariaDB [world]> SELECT * FROM user;
+----+-------+----------+---------------------+--------+
| id | name | password | regtime | deptid |
+----+-------+----------+---------------------+--------+
| 1 | test | test | 2018-03-05 17:25:26 | 1 |
| 2 | test1 | test1 | 2018-03-05 17:25:26 | 1 |
| 3 | lucy | lucy | 2018-03-05 17:25:26 | 2 |
| 4 | mars | mars | 2018-03-05 17:25:26 | 3 |
| 5 | mark | mark | 2018-03-05 17:26:05 | NULL |
+----+-------+----------+---------------------+--------+
5 rows in set (0.01 sec)
MariaDB [world]> SELECT * FROM department;
+----+------------+---------+----------+
| id | name | comment | adminids |
+----+------------+---------+----------+
| 1 | Sales | NULL | NULL |
| 2 | Tech | NULL | NULL |
| 3 | administra | NULL | NULL |
| 4 | Secretaria | NULL | NULL |
+----+------------+---------+----------+
4 rows in set (0.01 sec)
//其中deptid是用戶所屬部門的編號
我們有如下需求,顯示用戶及用戶所在部門名稱,根據(jù)我們上面所說的內(nèi)連接,我們可以寫出如下語句:
MariaDB [world]> SELECT user.id,user.name,department.name FROM user INNER JOIN department ON user.deptid = department.id;
+----+-------+------------+
| id | name | name |
+----+-------+------------+
| 1 | test | Sales |
| 2 | test1 | Sales |
| 3 | lucy | Tech |
| 4 | mars | administra |
+----+-------+------------+
4 rows in set (0.14 sec)
但是,結(jié)果對嗎?雖說我們的mark先生還沒有被分到任何部門,但是也不能不顯示人家了吧?
這時候,外連接就派上用場了:
在JOIN左面的表叫左表,而在右面的表叫右表
左外連接,F(xiàn)ROM tb1_name LEFT OUTER JOIN tb2_name
**除將符合條件的行顯示出來,還顯示左表的全部行,而右表的字段拼接過去全為NULL。**如下所示:
MariaDB [world]> SELECT * FROM user LEFT OUTER JOIN department ON user.deptid = department.id;
+----+-------+----------+---------------------+--------+------+------------+---------+----------+
| id | name | password | regtime | deptid | id | name | comment | adminids |
+----+-------+----------+---------------------+--------+------+------------+---------+----------+
| 1 | test | test | 2018-03-05 17:25:26 | 1 | 1 | Sales | NULL | NULL |
| 2 | test1 | test1 | 2018-03-05 17:25:26 | 1 | 1 | Sales | NULL | NULL |
| 3 | lucy | lucy | 2018-03-05 17:25:26 | 2 | 2 | Tech | NULL | NULL |
| 4 | mars | mars | 2018-03-05 17:25:26 | 3 | 3 | administra | NULL | NULL |
| 5 | mark | mark | 2018-03-05 17:26:05 | NULL | NULL | NULL | NULL | NULL |
+----+-------+----------+---------------------+--------+------+------------+---------+----------+
5 rows in set (0.00 sec)
右外連接,F(xiàn)ROM tb1_name RIGHT OUTER JOIN tb2_name
顧名思義,就是顯示右表的所有行,而未符合連接條件的行,左表字段全為NULL,如下所示:
MariaDB [world]> SELECT * FROM user RIGHT OUTER JOIN department ON user.deptid = department.id;
+------+-------+----------+---------------------+--------+----+------------+---------+----------+
| id | name | password | regtime | deptid | id | name | comment | adminids |
+------+-------+----------+---------------------+--------+----+------------+---------+----------+
| 1 | test | test | 2018-03-05 17:25:26 | 1 | 1 | Sales | NULL | NULL |
| 2 | test1 | test1 | 2018-03-05 17:25:26 | 1 | 1 | Sales | NULL | NULL |
| 3 | lucy | lucy | 2018-03-05 17:25:26 | 2 | 2 | Tech | NULL | NULL |
| 4 | mars | mars | 2018-03-05 17:25:26 | 3 | 3 | administra | NULL | NULL |
| NULL | NULL | NULL | NULL | NULL | 4 | Secretaria | NULL | NULL |
+------+-------+----------+---------------------+--------+----+------------+---------+----------+
5 rows in set (0.00 sec)
交叉連接與笛卡爾積
當(dāng)沒有連接條件的表進(jìn)行連接的結(jié)果為笛卡兒積,檢索出的行的數(shù)目將是第一個表中的行數(shù)乘以第二個表中的行數(shù),如下圖所示:
Mariadb學(xué)習(xí)總結(jié)(九):多表連接查詢Mariadb學(xué)習(xí)總結(jié)(九):多表連接查詢
如果有使用笛卡爾積的必要時,可以使用交叉連接(CROSS JOIN)如下例所示:
MariaDB [world]> SELECT user.Name,department.name FROM user CROSS JOIN department;
+-------+------------+
| Name | name |
+-------+------------+
| test | Sales |
| test | Tech |
| test | administra |
| test | Secretaria |
| test1 | Sales |
| test1 | Tech |
| test1 | administra |
| test1 | Secretaria |
| lucy | Sales |
| lucy | Tech |
| lucy | administra |
| lucy | Secretaria |
| mars | Sales |
| mars | Tech |
| mars | administra |
| mars | Secretaria |
| mark | Sales |
| mark | Tech |
| mark | administra |
| mark | Secretaria |
+-------+------------+
20 rows in set (0.00 sec)
多表連接的條件過濾
當(dāng)我們的想要過濾多表連接查詢結(jié)果時,我們可以將過濾條件放在ON子句或者WHERE子句,ON子句和WHERE子句得到的結(jié)果可能會不太一樣。
** 過濾條件放ON子句:使用AND邏輯與操作將過濾條件放在連接條件前或后->在連接前進(jìn)行條件過濾。** ** 過濾條件放WHERE子句:使用單獨(dú)的WHERE子句進(jìn)行數(shù)據(jù)過濾->在連接后進(jìn)行條件過濾。**
對于內(nèi)連接而言,過濾條件放在ON子句或WHERE子句是相同的,比較推薦在ON子句過濾。
而對于外連接而言,有以下情況參考:
//過濾條件放連接條件前或后
MariaDB [world]> SELECT user.name,department.name FROM user LEFT OUTER JOIN department ON user.name='mars' AND user.deptid = department.id;
MariaDB [world]> SELECT user.name,department.name FROM user LEFT OUTER JOIN department ON user.deptid = department.id AND user.name='mars';
+-------+------------+
| name | name |
+-------+------------+
| test | NULL |
| test1 | NULL |
| lucy | NULL |
| mars | administra |
| mark | NULL |
+-------+------------+
5 rows in set (0.00 sec)
//因?yàn)镺N user.name='mars'會將左表變?yōu)橐粭l數(shù)據(jù),但AND要求第二個表達(dá)式也為真,user.deptid = department.id;這條又僅過濾了mars的deptid和其部門表中對應(yīng)的id,但左連接又要求左表顯示所有數(shù)據(jù),所以右表字段為NULL
//過濾條件放WHERE子句,因?yàn)槭沁B接后進(jìn)行過濾,就是說對連接生成的這個新表過濾,所以只會顯示符合條件的這條數(shù)據(jù)。
MariaDB [world]> SELECT user.name,department.name FROM user LEFT OUTER JOIN department ON user.deptid = department.id WHERE user.name = 'mars';
+------+------------+
| name | name |
+------+------------+
| mars | administra |
+------+------------+
1 row in set (0.00 sec)
表的重命名
在多表連接查詢時,通常會對表進(jìn)行重命名操作,與列的重命名一樣使用AS關(guān)鍵字,對表重命名主要是引用表時使用方便。
如下所示,對user表重命名為U,對department重命名為D:
MariaDB [world]> SELECT U.name,D.name FROM user AS U LEFT OUTER JOIN department AS D ON
U.deptid = D.id;
+-------+------------+
| name | name |
+-------+------------+
| test | Sales |
| test1 | Sales |
| lucy | Tech |
| mars | administra |
| mark | NULL |
+-------+------------+
5 rows in set (0.01 sec)
多表連接與聚合函數(shù)的使用
多表連接查詢說白了就是產(chǎn)生一張臨時的新表,所以使用分組和聚合函數(shù)就像平常一樣簡單,參考如下例子:
統(tǒng)計(jì)每個部門的人數(shù):
MariaDB [world]> SELECT D.name,COUNT(U.name) FROM user AS U LEFT OUTER JOIN department AS D ON U.deptid = D.id GROUP BY D.name;
+------------+---------------+
| name | COUNT(U.name) |
+------------+---------------+
| NULL | 1 |
| administra | 1 |
| Sales | 2 |
| Tech | 1 |
+------------+---------------+
4 rows in set (0.00 sec)
統(tǒng)計(jì)每個城市所能說的官方語言的數(shù)量:
MariaDB [world]> SELECT C.Name,COUNT(CL.Language) FROM city AS C INNER JOIN countrylanguage AS CL ON C.CountryCode = CL.CountryCode AND CL.IsOfficial = 'T' GROUP BY C.Name;
+-------------------------+--------------------+
| Name | COUNT(CL.Language) |
+-------------------------+--------------------+
| A Coru?a (La Coru?a) | 1 |
| Aachen | 1 |
................................................
| Alicante [Alacant] | 1 |
| Aligarh | 1 |
+-------------------------+--------------------+
本文名稱:詳解Mariadb多表連接查詢
網(wǎng)站鏈接:http://www.dlmjj.cn/article/cccijig.html


咨詢
建站咨詢
