集合操作將多個查詢結果垂直合併,MySQL 支援 UNION DISTINCT(去重)與 UNION ALL(保留重複)。本文通過建表、插數、實戰對比,詳細講解語法規則、內部實現機制、性能差異與選型建議。
CREATE TABLE table1 (
aid INT NOT NULL AUTO_INCREMENT,
title VARCHAR(20),
tag VARCHAR(10),
PRIMARY KEY (aid)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE table2 (
bid INT NOT NULL AUTO_INCREMENT,
title VARCHAR(20),
tag VARCHAR(10),
PRIMARY KEY (bid)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO table1 (title, tag) VALUES
('article1','MySQL'), ('article2','PHP'), ('article3','CPP');
INSERT INTO table2 (title, tag) VALUES
('article1','MySQL'), ('article2','CPP'), ('article3','C');
(SELECT * FROM table1) UNION (SELECT * FROM table2);
結果(5 行,重複行 1, article1, MySQL 僅保留一份):
| aid | title | tag |
|---|---|---|
| 1 | article1 | MySQL |
| 2 | article2 | PHP |
| 3 | article3 | CPP |
| 2 | article2 | CPP |
| 3 | article3 | C |
代價:唯一索引維護開銷、臨時表可能轉磁盤(大結果集),性能顯著低於 UNION ALL。
(SELECT * FROM table1) UNION ALL (SELECT * FROM table2);
結果(6 行,重複行完整保留):
| aid | title | tag |
|---|---|---|
| 1 | article1 | MySQL |
| 2 | article2 | PHP |
| 3 | article3 | CPP |
| 1 | article1 | MySQL |
| 2 | article2 | CPP |
| 3 | article3 | C |
SELECT 列數必須相同,對應位置類型隱式轉換兼容;結果列名以第一個 SELECT 為準。ORDER BY / LIMIT:只能放在最後,或用括號包裹單獨 SELECT。UNION DISTINCT 可簡寫為 UNION。| 場景 | 推薦 | 理由 |
|---|---|---|
| 確知兩集合無重複 | UNION ALL | 無唯一索引開銷,直接流式輸出,速度快數倍 |
| 需要業務去重 | UNION DISTINCT | 語義正確,避免應用層再次去重 |
| 大結果集(>10萬行) | UNION ALL + 應用層去重 | 避免臨時表轉磁盤、唯一索引膨脹 |
| 分頁顯示合併結果 | UNION ALL + 書簽分頁 | 不需全量排序去重 |
UNION = 去重合併(內部唯一索引),UNION ALL = 直接合併。默認優先使用 UNION ALL,只有在確需去重且結果集可控時才用 UNION。大數據場景建議將去重邏輯下推到應用層或使用分區表/物化視圖預聚合。