多表連接查詢中的「多表」,可以是同一張表,自己和自己連接查詢。相當於(可以理解為) A 表自己先複製自己後再和自己連接,如此稱為「 自連接 」也可以在不同張表中連接查詢,可分為「內連接」、「交叉連接」、「外連接」。 內連接根據所使用的比較方式不同,又分為「等值連接」、「自然連接」和「不等連接」三種, ...
- 多表連接查詢中的「多表」,可以是同一張表,自己和自己連接查詢。相當於(可以理解為) A 表自己先複製自己後再和自己連接,如此稱為「 自連接 」也可以在不同張表中連接查詢,可分為「內連接」、「交叉連接」、「外連接」。
- 內連接根據所使用的比較方式不同,又分為「等值連接」、「自然連接」和「不等連接」三種,連接的結果只列出這些表中與連接條件相匹配的數據行。
- 與內連接不同的是,外連接不只列出與連接條件相匹配的行,而是列出左表(左外連接時)、右表(右外連接時)或兩個表(全外連接時)中所有符合搜索條件的數據行。外連接分為「左外連接」或「左連接」( OUTER JOIN 或 LEFT JOIN)、「右外連接」或「右連接」(RIGHT OUTER JOIN 或 RIGHT JOIN)和「全外連接」或「全連接」(FULL OUTER JOIN 或 FULL JOIN)三種。
數據模擬
mysql版本
select version();
sql語句
CREATE TABLE `bus_sche` (
`id` bigint NOT NULL AUTO_INCREMENT,
`lastStation` varchar(100) NOT NULL,
`nextStation` varchar(100) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
INSERT INTO test.bus_sche (lastStation,nextStation) VALUES
('武漢','南昌'),
('武漢','廣西'),
('南昌','廈門'),
('廣西','上海');
CREATE TABLE `Table_A` (
`id` bigint NOT NULL AUTO_INCREMENT,
`name` varchar(100) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
INSERT INTO test.Table_A (name) VALUES
('A1'),
('A3'),
('A4'),
('A8');
CREATE TABLE `Table_B` (
`id` bigint NOT NULL AUTO_INCREMENT,
`names` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
INSERT INTO test.Table_B (names) VALUES
('B1'),
('B2'),
('B3'),
('B5'),
('B6');
自連接
- 一張表中,假如有兩個以上的欄位,且這些欄位有一定的關係,我們又剛好想摸清這些關係欄位的數據,就可以在這上面做文章,俗稱「自連接」。
- 一張表 bus_sche,為了簡單,表中只有上一站地點和下一站地點及唯一標識
SELECT b.lastStation,b.nextStation,a.lastStation,a.nextStation
FROM bus_sche a, bus_sche b
WHERE b.nextStation = a.lastStation;
- 只在一張表中查詢,表 bus_sche 使用了兩個別名 bus_sche a, bus_sche b,因此相當於有兩張表,用 WHERE條件連接查詢,「 實際只有一張表在自我連接查詢」。
- 結果
內連接
- 在表中存在至少一個匹配時,INNER JOIN 關鍵字返回行。(內連接查詢操作只列出與連接條件匹配的數據行,使用 INNER JOIN 或者直接使用 **JOIN **進行連接)。
- 兩張表的 id ,A中有1、3、4、8,B中有1、2、3、5、6,還有一個欄位分別是 name 和names,該欄位數據都是按順序的小寫字母,前面再加個 A 或 B 為了方便區分屬於哪個表。
SELECT * from Table_A JOIN Table_B;
SELECT * from Table_A INNER JOIN Table_B;
- 內連接可以沒有連接條件,沒有條件之後的查詢結果,會保留所有結果(笛卡爾集),與交叉連接差不多。
等值連接
- 在連接條件中使用等於號(=)運算符比較被連接列的列值,其查詢結果中列出被連接表中的所有列,包括其中的重覆列
SELECT * from Table_A A JOIN Table_B B ON A.id = B.id;
- 查詢結果,列數是 4 列,兩張表的欄位直接拼接在一起,重覆的欄位在後面添加數字序列以做區分
- 通俗講就是根據條件,找到表 A 和 表 B 的數據的交集(包含重覆列)
不等連接
- 不等連接跟等值連接僅僅是連接條件中使用的運算符不一樣,其餘一致。不等連接使用的是除等於號運算符以外的其它比較運算符,如>、>=、<=、<、!>、!<和<> 等。
SELECT * from Table_A A JOIN Table_B B ON A.id < B.id;
- 根據條件,一個個做比較,滿足條件的所有結果
自然連接
- 在連接條件中使用等於(=)運算符比較被連接列的列值,但它使用選擇列表指出查詢結果集合中所包括的列,並刪除連接表中的重覆列。
SELECT * from Table_A NATURAL JOIN Table_B ;
SELECT * from Table_A A NATURAL JOIN Table_B B WHERE A.id = B.id;
- 查詢結果,註意是已經刪除了重覆列,列數只有 3,這也是和等值連接的區別
- 根據條件,找到表 A 和 表 B 的數據的交集,但欄位已經去重(不包含重覆列)
交叉連接
- 交叉連接不帶 WHERE 子句,它返回被連接的兩個表所有數據行的笛卡爾積。從一張表中迴圈取出每一條記錄,每條記錄都會去另一張表中匹配每一條記錄,匹配結果一定保留(因為無條件,如果有條件,則只保留滿足條件的結果)。
- 假設 A 表有 n 條記錄,B 表有 m 條記錄,則結果為 n * m 條記錄。
SELECT * from Table_A CROSS JOIN Table_B;
- 因為 A 表數據有 4 條,B 表數據有 5 條,4 x 5 = 20,因此交叉查詢結果有 20 條,如下
外連接
- 外連接不只列出與連接條件相匹配的行,而且還加上左表(左外連接時)或右表(右外連接時)或兩個表(全外連接時)中所有符合搜索條件的數據行。
左連接(左外連接)
- LEFT JOIN 關鍵字會從左表 (table_name1) 那裡返回所有的行,即使在右表 (table_name2) 中沒有匹配的行。
SELECT * from Table_A A LEFT JOIN Table_B B ON A.id = B.id;
SELECT * from Table_A A LEFT OUTER JOIN Table_B B ON A.id = B.id;
- 根據條件,用右表(B)匹配左表(A),能匹配,正確保留,不能匹配其他表的欄位都置空 Null。也就是,根據條件找到表 A 和 表 B 的數據的交集,再加上左表的數據集
左表唯一
SELECT * from Table_A A LEFT JOIN Table_B B ON A.id = B.id where B.id is null
右連接(右外連接)
- RIGHT JOIN 關鍵字會右表 (table_name2) 那裡返回所有的行,即使在左表 (table_name1) 中沒有匹配的行。
SELECT * from Table_A A RIGHT JOIN Table_B B ON A.id=B.id;
SELECT * from Table_A A RIGHT OUTER JOIN Table_B B ON A.id=B.id;
- 根據條件,用左表(A)匹配右表(B),能匹配,正確保留,不能匹配其他表的欄位都置空 Null。也就是,根據條件找到表 A 和 表 B 的數據的交集,再加上右表的數據集
右表唯一
SELECT * from Table_A A RIGHT OUTER JOIN Table_B B ON A.id=B.id
where A.id is null
多錶鏈接語句語法
-- 連接兩個數據表的用法:
FROM t1 INNER JOIN t2 ON t1.id=t2.id
-- 語法格式可以概括為:
FROM 表1 INNER JOIN 表2 ON 表1.欄位號=表2.欄位號
-- 連接三個數據表的用法:
FROM (t1 INNER JOIN t2 ON t1.id=t2.id) INNER JOIN t3 ON t1.name=t3.name
-- 語法格式可以概括為:
FROM (表1 INNER JOIN 表2 ON 表1.欄位號=表2.欄位號) INNER JOIN 表3 ON 表1.欄位號=表3.欄位號
-- 連接四個數據表的用法:
FROM ((t1 INNER JOIN t2 ON t1.id=t2.id) INNER JOIN t3 ON t1.name=t3.name) INNER JOIN t4 ON t1.city=t4.city
-- 語法格式可以概括為:
FROM ((表1 INNER JOIN 表2 ON 表1.欄位號=表2.欄位號) INNER JOIN 表3 ON 表1.欄位號=表3.欄位號) INNER JOIN 表4 ON 表1.欄位號=表4.欄位號
-- 連接五個數據表的用法:
FROM (((t1 INNER JOIN t2 ON t1.id=t2.id) INNER JOIN t3 ON t1.name=t3.name) INNER JOIN t4 ON t1.city=t4.city) INNER JOIN t5 ON t1.country=t5.country
-- 語法格式可以概括為:
FROM (((表1 INNER JOIN 表2 ON 表1.欄位號=表2.欄位號) INNER JOIN 表3 ON 表1.欄位號=表3.欄位號) INNER JOIN 表4 ON 表1.欄位號=表4.欄位號) INNER JOIN 表5 ON 表1.欄位號=表5.欄位號
全鏈接(全外連接)
- 根據條件找到表 A 和 表 B 的數據的交集,再加上左右表的數據集
SQL Server版本
SELECT * FROM Table_A A FULL OUTER JOIN Table_B B ON A.id = B.id;
- 此查詢將返回左表(表A)中的所有記錄和右表(表B)中所有不匹配的記錄
SELECT * FROM Table_A A FULL OUTER JOIN Table_B B ON A.id = B.id
WHERE A.id IS NULL OR B.id IS NULL;