萬盛學電腦網

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

MySQL 多表查詢完全指南:UNION、JOIN、子查詢選型與效能優化實戰

多表查詢是 SQL 進階的核心戰場。本文系統梳理 UNION、各類 JOIN、子查詢的語法差異、適用場景與效能特徵,並提供「如何選擇最佳方案」的決策樹,助你寫出既正確又高效的多表查詢。

UNION 與 UNION ALL:縱向合併結果集

-- UNION:去重(預設),效能較差
SELECT a1 FROM table1 UNION SELECT a1 FROM table2;

-- UNION ALL:保留重複,效能優,業務允許重複時首選
SELECT a1 FROM table1 UNION ALL SELECT a1 FROM table2;
  • 欄位數、順序、型別必須相容
  • ORDER BY、LIMIT 需包在子查詢或最外層
  • 適用:同結構分表合併、歷史/現存資料統一查詢

JOIN 家族全景圖

實戰範例:用戶與操作記錄

-- 用戶表
id | name
1  | libk
2  | zyfon
3  | daodao

-- 操作表
user_id | action
1       | jump
1       | kick
2       | run
4       | swim

-- LEFT JOIN:所有用戶 + 操作(無操作顯示 NULL)
SELECT u.id, u.name, a.action
FROM `user` u
LEFT JOIN user_action a ON u.id = a.user_id;
/* 結果:
1 libk jump
1 libk kick
2 zyfon run
3 daodao NULL
※ user_id=4 的 swim 不出現(右表孤兒) */

反向查詢:找出「在左表不在右表」的資料

SELECT u.id, u.name
FROM `user` u
LEFT JOIN user_action a ON u.id = a.user_id
WHERE a.user_id IS NULL;  -- 必須用 IS NULL,且判斷欄位為 NOT NULL
/* 結果:3 daodao */

多表連接順序與優化器

  • MySQL 優化器自動決定連接順序,但 LEFT JOIN 強制左表優先讀取
  • 錯誤順序導致全表掃描:FROM a,b LEFT JOIN c ON ... WHERE b.key=d.key → 改為 FROM b,a LEFT JOIN c ...
  • 強制順序:STRAIGHT_JOIN 或調整 FROM 子句順序

索引提示:USE INDEX / IGNORE INDEX

SELECT * FROM t1 USE INDEX (idx_a) WHERE a=1 AND b=2;
SELECT * FROM t1 IGNORE INDEX (idx_b) WHERE a=1 AND b=2;

連接條件三寫法對比

類型關鍵字語意典型場景
內連接INNER JOIN / JOIN僅返回雙方匹配行主從表關聯、維度表查詢
左外連接LEFT [OUTER] JOIN左表全保留,右表無匹配填 NULL主表帶明細、報表保留主維度
右外連接RIGHT [OUTER] JOIN右表全保留極少用,可改 LEFT JOIN 交換表順序
交叉連接CROSS JOIN / ,笛卡爾積(無條件)生成測試資料、矩陣運算

選型決策樹

  1. 需「縱向合併同結構資料」→ UNION ALL(去重才用 UNION)
  2. 需「橫向展開關聯資料」→ 進入 JOIN 選型:
    • 主表全保留、從表可無 → LEFT JOIN
    • 雙方必須都存在 → INNER JOIN
    • 從表全保留 → 改寫為 LEFT JOIN 交換順序
  3. 子查詢可改寫為 JOIN 時 → 優先改寫(衍生表物化開銷大)
  4. 大表關聯 → 確保連接欄位有索引、考慮分區/分表
多表查詢的藝術在於「用最少的掃描換取最精確的結果」。先想業務語意,再選語法,最後用 EXPLAIN 驗證執行計畫,是通往高效 SQL 的唯一捷徑。
copyright © 萬盛學電腦網 all rights reserved
寫法範例適用場景
WHEREWHERE t1.id = t2.id內連接、舊語法
ONLEFT JOIN t2 ON t1.id = t2.id外連接、複雜條件、標準語法
USINGJOIN t2 USING (id)同名欄位連接,簡潔但不支援別名前綴