實務常見需求:兩張表分別儲存不同業務資料(如:orders 訂單表、region 區域表),需在單一結果集中並排顯示前 N 筆記錄,供前端一次渲染。
(SELECT customer_id AS col1, NULL AS col2 FROM orders LIMIT 2) UNION ALL (SELECT NULL, region_description FROM region LIMIT 2);
UNION ALL 不去重,比 UNION 快NULL 佔位SELECT o.customer_id, r.region_description FROM orders o JOIN region r ON o.region_id = r.region_id LIMIT 2;
region_id)原文範例使用 T-SQL(SQL Server)語法,MySQL 寫法如下:
DELIMITER $$
CREATE PROCEDURE merge_two_tables()
BEGIN
DECLARE v_col1 VARCHAR(20);
DECLARE v_col2 VARCHAR(20);
DECLARE done INT DEFAULT 0;
-- 臨時表
CREATE TEMPORARY TABLE tmp_merge (
id INT AUTO_INCREMENT PRIMARY KEY,
col1 VARCHAR(20),
col2 VARCHAR(20)
);
-- 兩個游標
DECLARE cur1 CURSOR FOR SELECT customer_id FROM orders LIMIT 2;
DECLARE cur2 CURSOR FOR SELECT region_description FROM region LIMIT 2;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
OPEN cur1;
OPEN cur2;
read_loop: LOOP
FETCH cur1 INTO v_col1;
FETCH cur2 INTO v_col2;
IF done THEN LEAVE read_loop; END IF;
INSERT INTO tmp_merge (col1, col2) VALUES (v_col1, v_col2);
END LOOP;
CLOSE cur1;
CLOSE cur2;
SELECT * FROM tmp_merge;
DROP TEMPORARY TABLE tmp_merge;
END$$
DELIMITER ;
微服務架構下,建議由應用層並行查詢兩表,記憶體中組裝 JSON 回傳:
# Python pseudocode
orders = db.query("SELECT customer_id FROM orders LIMIT 2")
regions = db.query("SELECT region_description FROM region LIMIT 2")
result = [{"order": o, "region": r} for o, r in zip(orders, regions)]
return jsonify(result)
| 方案 | 適用場景 | 優點 | 缺點 | 建議指數 |
|---|---|---|---|---|
| JOIN | 有關聯鍵,需合併欄位 | 標準 SQL、優化器支援好 | 大表 JOIN 易慢 | ★★★★★ |
| UNION ALL | 同結構、不同來源垂直拼接 | 簡單、快、無去重開銷 | 需欄位對齊 | ★★★★☆ |
| 臨時表+游標 | 無關聯鍵、需順序配對、複雜邏輯 | 彈性最大 | 慢、佔資源、難維護 | ★★☆☆☆ |
| 應用層組裝 | 微服務、前端分離、高併發 | 解耦、擴展性強 | 網路往返、程式碼較多 | ★★★★★ |
WITH cte1 AS (SELECT customer_id FROM orders LIMIT 2),
cte2 AS (SELECT region_description FROM region LIMIT 2)
SELECT c1.customer_id, c2.region_description
FROM cte1 c1
JOIN cte2 c2 ON 1=1; -- 無關聯鍵強制配對,實際需加 ROW_NUMBER()
MySQL 8.0 支援 ROW_NUMBER() OVER () 產生行號,可完美替代游標配對邏輯。