表1(采購計劃)、表2(實際采購)結構相同,需按類型+名稱分組,輸出計劃數與實際數對比。
表1: type, name, plan_qty
表2: type, name, actual_qty
type | name | plan_qty | actual_qty
文具 | 鉛筆 | 2 | 1
耗材 | 紙 | 10 | 1
SELECT
type,
name,
SUM(plan_qty) AS plan_qty,
SUM(actual_qty) AS actual_qty
FROM (
SELECT type, name, qty AS plan_qty, 0 AS actual_qty FROM table1
UNION ALL
SELECT type, name, 0 AS plan_qty, qty AS actual_qty FROM table2
) t
GROUP BY type, name
ORDER BY type, name;
SELECT
COALESCE(t1.type, t2.type) AS type,
COALESCE(t1.name, t2.name) AS name,
t1.plan_qty,
t2.actual_qty
FROM (
SELECT type, name, SUM(qty) AS plan_qty FROM table1 GROUP BY type, name
) t1
FULL OUTER JOIN (
SELECT type, name, SUM(qty) AS actual_qty FROM table2 GROUP BY type, name
) t2 ON t1.type = t2.type AND t1.name = t2.name;
優點:單次掃描聚合後連接。缺點:MySQL 不支持 `FULL OUTER JOIN`,需 `UNION` 模擬。
SELECT type, name, SUM(plan_qty), SUM(actual_qty) FROM (
SELECT type, name, qty AS plan_qty, 0 AS actual_qty FROM table1
UNION ALL
SELECT type, name, 0, qty FROM table2
) t GROUP BY type, name;
| 錯誤寫法 | 問題 | 修正 |
|---|---|---|
| 直接 JOIN 兩表 | 笛卡爾積、數據膨脹 | 先聚合再 JOIN 或 UNION ALL |
| 用 UNION(去重) | 丟失重複類型+名稱行 | 用 UNION ALL |
| 不加 GROUP BY | 聚合錯誤 | 必須 GROUP BY type, name |
兩表同結構分類匯總,UNION ALL 合併後 GROUP BY 是最通用、兼容性最好、性能穩健的方案。MySQL 用此法;PostgreSQL/Oracle/SQL Server 可用 `FULL OUTER JOIN` 簡化。