首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> MySQL 資料庫 >> MySQL 綜合教學

MySQL 多表連接查詢完全指南:內連接、外連接、自然連接與多表關聯實戰

     編輯:MySQL 綜合教學

核心思路

連接查詢將多張表按條件組合成虛擬大表,再進行篩選投影。分類依據連接條件與結果集保留邏輯:

準備數據

CREATE TABLE teacher (id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(10), gender ENUM('male','female','secret')) ENGINE=InnoDB CHARSET=utf8;
INSERT INTO teacher VALUES (NULL,'奧巴馬','male'),(NULL,'楊冪','female'),(NULL,'rose','secret'),(NULL,'阿黛爾','female');

CREATE TABLE grade (id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(10), room VARCHAR(3)) ENGINE=InnoDB CHARSET=utf8;
INSERT INTO grade VALUES (NULL,'bigdata','203'),(NULL,'english','207'),(NULL,'maths','308'),(NULL,'PE','228');

CREATE TABLE teacher_grade (id INT PRIMARY KEY AUTO_INCREMENT, t_id INT, c_id INT, day TINYINT, begin_date DATE, end_date DATE) ENGINE=InnoDB CHARSET=utf8;
INSERT INTO teacher_grade VALUES
(NULL,1,1,15,'2015-01-15','2015-01-30'),
(NULL,1,2,18,'2015-02-10','2015-02-28'),
(NULL,1,3,22,'2015-03-01','2015-03-23'),
(NULL,2,1,20,'2015-03-05','2015-03-25'),
(NULL,2,2,22,'2015-04-08','2015-04-30'),
(NULL,3,1,15,'2015-05-01','2015-05-16'),
(NULL,1,1,15,'2015-05-05','2015-05-20'),
(NULL,3,3,15,'2015-07-01','2015-07-16'),
(NULL,2,1,5,'2015-06-17','2015-06-23');

一、內連接

僅返回雙方均滿足條件的行。語法:tbl_left INNER JOIN tbl_right ON 條件。

-- 推薦寫法:ON 放連接條件,WHERE 放過濾條件
SELECT t.name, tg.day, tg.begin_date
FROM teacher AS t
INNER JOIN teacher_grade AS tg ON t.id = tg.t_id
WHERE tg.day >= 20;

連接條件的三種寫法

寫法示例特點
ONON t.id = tg.t_id通用,連接時過濾,推薦
WHEREWHERE t.id = tg.t_id笛卡爾積後過濾,內連接等價但語義不清
USINGUSING (id)要求同名列,結果集自動去重該列

無條件內連接 = 交叉連接(笛卡爾積)

SELECT * FROM teacher INNER JOIN teacher_grade;  -- 4×9=36 行
SELECT * FROM teacher CROSS JOIN teacher_grade;  -- 同義

二、外連接

保留一方不滿足條件的行,另一方用 NULL 填充。MySQL 不支持 FULL OUTER JOIN,可用 UNION 模擬。

左外連接

SELECT t.id AS teacher_id, tg.id AS teacher_grade_id, t.name, tg.day, tg.begin_date
FROM teacher AS t
LEFT OUTER JOIN teacher_grade AS tg ON t.id = tg.t_id;

左表所有行保留,右表無匹配則 NULL。

右外連接

SELECT t.id AS teacher_id, tg.id AS teacher_grade_id, t.name, tg.day, tg.begin_date
FROM teacher AS t
RIGHT OUTER JOIN teacher_grade AS tg ON t.id = tg.t_id;

右表所有行保留,左表無匹配則 NULL。

全外連接模擬

(SELECT ... FROM teacher LEFT JOIN teacher_grade ON ...)
UNION
(SELECT ... FROM teacher RIGHT JOIN teacher_grade ON ...);

⚠️ 外連接禁用 WHERE 作連接條件

外連接中 WHERE 會過濾掉 NULL 行,破壞外連接語義。連接條件必須寫在 ON 或 USING 中。

三、自然連接

MySQL 自動根據同名列連接,無需指定條件。分為 NATURAL JOIN(內)、NATURAL LEFT JOIN、NATURAL RIGHT JOIN。

SELECT * FROM one NATURAL JOIN two;
-- 等價於
SELECT * FROM one INNER JOIN two USING (public_field);

四、多表連接與別名最佳實踐

三表連接示例

SELECT s.*, si.*
FROM info_class AS c
LEFT JOIN info_student AS s ON c.id = s.class_id
LEFT JOIN info_student_info AS si ON s.id = si.id
WHERE c.class_name = '001';

同表多次連接(自連接)

SELECT m.*, h.class_name AS host, g.class_name AS guest
FROM match AS m
LEFT JOIN class AS h ON m.host_id = h.id
LEFT JOIN class AS g ON m.guest_id = g.id;

五、列別名與表別名規範

  • 表別名:簡短有義(t、tg),提升可讀性;
  • 列別名:消除同名衝突(t.id AS teacher_id),前端映射友好;
  • 前綴原則:列名無歧義可省略表前綴,有歧義必須加,建議統一加上便於維護。

六、性能優化提示

  1. 驅動表(小表/過濾後行數少)放左側,被驅動表加索引;
  2. 使用 EXPLAIN 檢查 type=ref/eq_ref、rows 預估;
  3. 避免 SELECT *,僅選取所需列減少網絡與內存開銷;
  4. 大表連接考慮 STRAIGHT_JOIN 固定驅動順序,或調整 join_buffer_size。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved