萬盛學電腦網

您现在的位置: 萬盛學電腦網 >> 程式設計 >  >> 資料庫 >> MySQL 教學

SQL JOIN 關聯查詢實戰:INNER/LEFT/RIGHT/FULL JOIN、多表關聯、效能優化

SQL JOIN 多表關聯查詢完全指南

JOIN` 根據關聯欄位將多張表資料水平合併。掌握 `INNER`、`LEFT`、`RIGHT`、`FULL`、`CROSS` 五種連接類型、多表鏈式關聯、效能優化是 SQL 進階必修。

五大 JOIN 類型圖解

類型關鍵字結果集Venn 圖
內連接INNER JOIN / JOIN兩表**匹配**的行交集
左外連接LEFT [OUTER] JOIN左表**所有**行 + 右表匹配行 (無匹配為 NULL)左圓完整
右外連接RIGHT [OUTER] JOIN右表**所有**行 + 左表匹配行右圓完整
全外連接FULL [OUTER] JOIN兩表**所有**行 (無匹配為 NULL)並集
交叉連接CROSS JOIN笛卡爾積 (所有組合)矩形

基礎語法


-- 內連接 (最常用)
SELECT t1.col1, t2.col2
FROM table1 t1
INNER JOIN table2 t2 ON t1.common_col = t2.common_col;

-- 左連接 (保留左表所有)
SELECT t1.col1, t2.col2
FROM table1 t1
LEFT JOIN table2 t2 ON t1.common_col = t2.common_col;

-- 多表鏈式關聯
SELECT u.name, o.order_no, oi.product_name, oi.quantity
FROM users u
INNER JOIN orders o ON u.id = o.user_id
INNER JOIN order_items oi ON o.id = oi.order_id
WHERE u.status = 'active';

實戰範例

範例 1:列出所有人的訂單 (含無訂單用戶)


SELECT p.lastname, p.firstname, o.orderno
FROM persons p
LEFT JOIN orders o ON p.id_p = o.id_p;
-- 無訂單用戶:orderno 為 NULL

範例 2:專輯與曲目關聯查詢


SELECT a.title, t.artist
FROM album a
JOIN track t ON a.asin = t.album
WHERE t.song = 'Alison';

範例 3:舊式 WHERE 關聯語法 (不推薦)


SELECT p.lastname, p.firstname, o.orderno
FROM persons p, orders o
WHERE p.id_p = o.id_p;
-- 隱式內連接,易寫成笛卡爾積,現代 SQL 建議顯式 JOIN

進階 JOIN 技巧

多條件關聯


SELECT * FROM orders o
JOIN customers c ON o.customer_id = c.id AND c.status = 'active'
JOIN addresses a ON c.id = a.customer_id AND a.is_default = 1;

自關聯 (層級結構)


-- 員工-經理關係
SELECT e.name AS employee, m.name AS manager
FROM employees e
LEFT JOIN employees m ON e.manager_id = m.id;

派生表/子查詢關聯


SELECT u.name, recent_orders.cnt
FROM users u
LEFT JOIN (
    SELECT user_id, COUNT(*) AS cnt
    FROM orders 
    WHERE created_at >= DATE_SUB(NOW(), INTERVAL 30 DAY)
    GROUP BY user_id
) recent_orders ON u.id = recent_orders.user_id;

側向關聯 / LATERAL JOIN (PostgreSQL/MySQL 8.0.14+)


-- 每個用戶取最新 3 筆訂單
SELECT u.name, o.*
FROM users u
CROSS JOIN LATERAL (
    SELECT * FROM orders 
    WHERE user_id = u.id 
    ORDER BY created_at DESC LIMIT 3
) o;

效能優化核心原則

原則說明實踐
小表驅動大表驅動表 (外層) 應為結果集較小者WHERE 過濾先執行、或用子查詢縮小驅動表
關聯欄位建索引ON 條件欄位必須有索引複合索引順序匹配 JOIN 順序
避免 SELECT *只取需要欄位,減少傳輸、利用覆蓋索引明確列出欄位
WHERE 先於 JOIN 過濾減少參與 JOIN 的行數條件下推、分區裁剪
優先 INNER JOIN優化器選擇空間大外連接限制優化器重排序

EXPLAIN 分析關鍵欄位

  • type:system > const > eq_ref > ref > range > index > ALL (越前越好)
  • key:實際使用的索引
  • rows:預估掃描行數
  • Extra:Using where, Using index (覆蓋索引), Using temporary, Using filesort

常見反模式

  • 笛卡爾積:忘寫 ON 條件 或 條件無匹配
  • 隱式轉換:VARCHAR join INT 導致索引失效
  • 大表 LEFT JOIN 大表:產生巨大中間結果集
  • 子查詢未去相關化:IN (SELECT ...) 可改寫為 JOIN

MySQL 8.0+ 新特性

  • LATERAL JOIN / CROSS JOIN LATERAL
  • WITH (CTE) 簡化複雜多表查詢
  • INTERSECT / EXCEPT 集合運算替代複雜 JOIN
  • 隱式索引合併 (Index Merge) 改進
copyright © 萬盛學電腦網 all rights reserved