1. 程式人生 > 實用技巧 >msyq 資料庫 表內連線 外連線 全連線 基本操作

msyq 資料庫 表內連線 外連線 全連線 基本操作

準備:

角色表:

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for role
-- ----------------------------
DROP TABLE IF EXISTS `role`;
CREATE TABLE `role` (
`id` int(11) NOT NULL,
`name` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_bin ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of role
-- ----------------------------
INSERT INTO `role` VALUES (1, '超級管理員');
INSERT INTO `role` VALUES (2, '管理員');
INSERT INTO `role` VALUES (3, '員工');

SET FOREIGN_KEY_CHECKS = 1;

角色選單表

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for role_menu
-- ----------------------------
DROP TABLE IF EXISTS `role_menu`;
CREATE TABLE `role_menu` (
`role_id` int(11) NOT NULL,
`menu_id` int(11) NOT NULL
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_bin ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of role_menu
-- ----------------------------
INSERT INTO `role_menu` VALUES (1, 3);
INSERT INTO `role_menu` VALUES (1, 2);
INSERT INTO `role_menu` VALUES (1, 4);
INSERT INTO `role_menu` VALUES (1, 6);
INSERT INTO `role_menu` VALUES (1, 7);
INSERT INTO `role_menu` VALUES (1, 9);
INSERT INTO `role_menu` VALUES (10, 10);

SET FOREIGN_KEY_CHECKS = 1;

一.Join語法概述

join 用於多表中欄位之間的聯絡,語法如下:

... FROM table1 INNER|LEFT|RIGHT JOIN table2 ON conditiona 

table1:左表;table2:右表。

JOIN 按照功能大致分為如下三類:

  • INNER JOIN(內連線,或等值連線):取得兩個表中存在連線匹配關係的記錄。
  • LEFT JOIN(左連線):取得左表(table1)完全記錄,即是右表(table2)並無對應匹配記錄。
  • RIGHT JOIN(右連線):與 LEFT JOIN 相反,取得右表(table2)完全記錄,即是左表(table1)並無匹配對應記錄。

注意:mysql不支援Full join,不過可以通過UNION 關鍵字來合併 LEFT JOIN 與 RIGHT JOIN來模擬FULL join.

二.Inner join

內連線,也叫等值連線,inner join產生同時符合A和B的一組資料。

select *from role a innser join role_menu b on a.id=b.role_id

三.Left join

(1)

select *from role a left join role_menu b on a.id=b.role_id

left join,(或left outer join:在Mysql中兩者等價,推薦使用left join.)左連線從左表(A)產生一套完整的記錄,與匹配的記錄(右表(B)) .如果沒有匹配,右側將包含null。

(2)

如果想只從左表(A)中產生一套記錄,但不包含右表(B)的記錄,可以通過設定where語句來執行,如下:


select *from role a left join role_menu b on a.id=b.role_id where b.role_id is null

(3)求差集:

根據上面的例子可以求差集,如下:

select *from role a left join role_menu b on a.id=b.role_id where b.role_id is null

union

select *from role a right join role_menu b on a.id=b.role_id where a.id is null

四.Right join

mysql> select * from A right join B on A.name = B.name;
+------+--------+----+-------------+
| id   | name   | id | name        |
+------+--------+----+-------------+
| NULL | NULL   |  1 | Rutabaga    |
|    1 | Pirate |  2 | Pirate      |
| NULL | NULL   |  3 | Darth Vader |
|    3 | Ninja  |  4 | Ninja       |
+------+--------+----+-------------+
4 rows in set (0.00 sec)

同left join。

五.Cross join

cross join:交叉連線,得到的結果是兩個表的乘積,即笛卡爾積

笛卡爾(Descartes)乘積又叫直積。假設集合A={a,b},集合B={0,1,2},則兩個集合的笛卡爾積為{(a,0),(a,1),(a,2),(b,0),(b,1), (b,2)}。可以擴充套件到多個集合的情況。類似的例子有,如果A表示某學校學生的集合,B表示該學校所有課程的集合,則A與B的笛卡爾積表示所有可能的選課情況。

mysql> select * from A cross join B;
+----+-----------+----+-------------+
| id | name      | id | name        |
+----+-----------+----+-------------+
|  1 | Pirate    |  1 | Rutabaga    |
|  2 | Monkey    |  1 | Rutabaga    |
|  3 | Ninja     |  1 | Rutabaga    |
|  4 | Spaghetti |  1 | Rutabaga    |
|  1 | Pirate    |  2 | Pirate      |
|  2 | Monkey    |  2 | Pirate      |
|  3 | Ninja     |  2 | Pirate      |
|  4 | Spaghetti |  2 | Pirate      |
|  1 | Pirate    |  3 | Darth Vader |
|  2 | Monkey    |  3 | Darth Vader |
|  3 | Ninja     |  3 | Darth Vader |
|  4 | Spaghetti |  3 | Darth Vader |
|  1 | Pirate    |  4 | Ninja       |
|  2 | Monkey    |  4 | Ninja       |
|  3 | Ninja     |  4 | Ninja       |
|  4 | Spaghetti |  4 | Ninja       |
+----+-----------+----+-------------+
16 rows in set (0.00 sec)

#再執行:mysql> select * from A inner join B; 試一試

#在執行mysql> select * from A cross join B on A.name = B.name; 試一試

實際上,在 MySQL 中(僅限於 MySQL) CROSS JOIN 與 INNER JOIN 的表現是一樣的,在不指定 ON 條件得到的結果都是笛卡爾積,反之取得兩個表完全匹配的結果。
INNER JOIN 與 CROSS JOIN 可以省略 INNER 或 CROSS 關鍵字,因此下面的 SQL 效果是一樣的:

... FROM table1 INNER JOIN table2
... FROM table1 CROSS JOIN table2
... FROM table1 JOIN table2 

六.Full join(取並集)

(1)
select *from role a left join role_menu b on a.id=b.role_id
union all

select *from role a right join role_menu b on a.id=b.role_id

(2)

select *from role a left join role_menu b on a.id=b.role_id
union

select *from role a right join role_menu b on a.id=b.role_id

(1)和(2)的區別:union和union all 的區別就是 交集部分重複的是否去重

全連線產生的所有記錄(雙方匹配記錄)在表A和表B。如果沒有匹配,則對面將包含null。