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

成都創(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)
比如其上兩張表,我們想知道某一城市所使用的語(yǔ)言,就可以分為兩個(gè)步驟:
1.在City表中查詢?cè)摮鞘械腃ountryCode。
2.使用查詢到的這個(gè)CountryCode在CountryLanguage表中查詢?cè)搰?guó)家所使用的語(yǔ)言。
雖然,可以分兩步完成,但是,需要兩次查詢和兩次傳輸,在帶寬和性能的對(duì)比下,我們更希望讓Mysql(MariaDB)來(lái)幫助我們完成這件事不是嗎?
連接(JOIN):也叫連結(jié),是指將兩張表按照一定規(guī)則連成一張表,將兩張表中不同的數(shù)據(jù)(行)連成一行來(lái)看待。
又可以將連接分為如下幾類:
-
內(nèi)連接
-
外連接
-
-
左外連接
-
右外連接
-
-
交叉連接
在連接查詢中,一個(gè)列可能出現(xiàn)在多張表中,為了避免引起歧義,通常在列名前面加上表名或表別名作為前綴(例:s.sid、x.sid)—使用表別名作為前綴,可以使得SQL代碼較短,使用的內(nèi)存更少(例:stu s,xuanke as x)。
內(nèi)連接
內(nèi)連接語(yǔ)法如下:
SELECT tb1_name.column,tb2_name.column FROM tb1 INNER JOIN tb2 ON 約束條件;
SELECT tb1_name.column,tb2_name.column FROM tb1,tb2 WHERE 約束條件;
查詢每一個(gè)城市可能使用的語(yǔ)言有哪些:
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)連接是怎樣工作的
我們來(lái)看一下,這些數(shù)據(jù)是怎么連接起來(lái)的,具體可以看如下這張圖(放大看):
所以所謂內(nèi)連接,就是僅將多表中符合條件的行進(jìn)行連接且返回結(jié)果。
比如這樣,就將三張表連接了起來(lái):
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子句多連接出來(lái)的表進(jìn)行過(guò)濾呀,且此語(yǔ)法結(jié)構(gòu)更清晰不是嗎?
外連接
使用內(nèi)連接會(huì)將多表中符合條件的行連接到一起,而不符合條件的行則忽略,而外連接則會(huì)將一些不符合條件的行也輸出出來(lá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是用戶所屬部門的編號(hào)
我們有如下需求,顯示用戶及用戶所在部門名稱,根據(jù)我們上面所說(shuō)的內(nèi)連接,我們可以寫出如下語(yǔ)句:
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é)果對(duì)嗎?雖說(shuō)我們的mark先生還沒有被分到任何部門,但是也不能不顯示人家了吧?
這時(shí)候,外連接就派上用場(chǎng)了:
在JOIN左面的表叫左表,而在右面的表叫右表
左外連接,F(xiàn)ROM tb1_name LEFT OUTER JOIN tb2_name
**除將符合條件的行顯示出來(lái),還顯示左表的全部行,而右表的字段拼接過(guò)去全為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ù)目將是第一個(gè)表中的行數(shù)乘以第二個(gè)表中的行數(shù),如下圖所示:
Mariadb學(xué)習(xí)總結(jié)(九):多表連接查詢Mariadb學(xué)習(xí)總結(jié)(九):多表連接查詢
如果有使用笛卡爾積的必要時(shí),可以使用交叉連接(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)
多表連接的條件過(guò)濾
當(dāng)我們的想要過(guò)濾多表連接查詢結(jié)果時(shí),我們可以將過(guò)濾條件放在ON子句或者WHERE子句,ON子句和WHERE子句得到的結(jié)果可能會(huì)不太一樣。
** 過(guò)濾條件放ON子句:使用AND邏輯與操作將過(guò)濾條件放在連接條件前或后->在連接前進(jìn)行條件過(guò)濾。** ** 過(guò)濾條件放WHERE子句:使用單獨(dú)的WHERE子句進(jìn)行數(shù)據(jù)過(guò)濾->在連接后進(jìn)行條件過(guò)濾。**
對(duì)于內(nèi)連接而言,過(guò)濾條件放在ON子句或WHERE子句是相同的,比較推薦在ON子句過(guò)濾。
而對(duì)于外連接而言,有以下情況參考:
//過(guò)濾條件放連接條件前或后
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'會(huì)將左表變?yōu)橐粭l數(shù)據(jù),但AND要求第二個(gè)表達(dá)式也為真,user.deptid = department.id;這條又僅過(guò)濾了mars的deptid和其部門表中對(duì)應(yīng)的id,但左連接又要求左表顯示所有數(shù)據(jù),所以右表字段為NULL
//過(guò)濾條件放WHERE子句,因?yàn)槭沁B接后進(jìn)行過(guò)濾,就是說(shuō)對(duì)連接生成的這個(gè)新表過(guò)濾,所以只會(huì)顯示符合條件的這條數(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)
表的重命名
在多表連接查詢時(shí),通常會(huì)對(duì)表進(jìn)行重命名操作,與列的重命名一樣使用AS關(guān)鍵字,對(duì)表重命名主要是引用表時(shí)使用方便。
如下所示,對(duì)user表重命名為U,對(duì)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ù)的使用
多表連接查詢說(shuō)白了就是產(chǎn)生一張臨時(shí)的新表,所以使用分組和聚合函數(shù)就像平常一樣簡(jiǎn)單,參考如下例子:
統(tǒng)計(jì)每個(gè)部門的人數(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ì)每個(gè)城市所能說(shuō)的官方語(yǔ)言的數(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多表連接查詢
標(biāo)題網(wǎng)址:http://m.fisionsoft.com.cn/article/cccijig.html


咨詢
建站咨詢
