需對表 B 進行多區間統計(如金額分段),結果橫向展示在表 A 查詢中。提問者擔心多次 LEFT JOIN 重複代碼、效率低,尋求合併寫法。
經驗證,多次左連接子查詢在主流數據庫(SQL Server、MySQL、PostgreSQL、Oracle)中執行計劃最優、可維護性最強。嘗試合併反而導致:
UNION ALL + 條件聚合:掃描表 B 多次,無法利用索引區間查詢CASE WHEN 條件聚合:單次掃描但需全表掃描,無區間索引求值
SELECT
a.id,
a.name,
COALESCE(b1.cnt, 0) AS range_1000_5000,
COALESCE(b2.cnt, 0) AS range_5000_10000,
COALESCE(b3.cnt, 0) AS range_10000_20000
FROM A a
LEFT JOIN (
SELECT branch_id, COUNT(*) cnt
FROM B
WHERE amount >= 1000 AND amount < 5000
GROUP BY branch_id
) b1 ON a.branch_id = b1.branch_id
LEFT JOIN (
SELECT branch_id, COUNT(*) cnt
FROM B
WHERE amount >= 5000 AND amount < 10000
GROUP BY branch_id
) b2 ON a.branch_id = b2.branch_id
LEFT JOIN (
SELECT branch_id, COUNT(*) cnt
FROM B
WHERE amount >= 10000 AND amount < 20000
GROUP BY branch_id
) b3 ON a.branch_id = b3.branch_id
WHERE a.status = 1
ORDER BY a.name;
| 優化點 | 說明 | 效果 |
|---|---|---|
| 子查詢預聚合 | 先 GROUP BY 再 JOIN,減少 JOIN 行數 | ⭐⭐⭐⭐⭐ |
| 區間索引 | B 表建立 INDEX (branch_id, amount) | ⭐⭐⭐⭐⭐ |
| 覆蓋索引 | 索引包含所有查詢列,避免回表 | ⭐⭐⭐⭐ |
| 分區表 | 大數據量按 amount 分區 | ⭐⭐⭐⭐ |
| 物化視圖 | 定時刷新預計算結果 | ⭐⭐⭐⭐⭐ |
SELECT
a.id,
a.name,
COUNT(CASE WHEN b.amount BETWEEN 1000 AND 4999 THEN 1 END) AS range_1000_5000,
COUNT(CASE WHEN b.amount BETWEEN 5000 AND 9999 THEN 1 END) AS range_5000_10000,
COUNT(CASE WHEN b.amount BETWEEN 10000 AND 19999 THEN 1 END) AS range_10000_20000
FROM A a
LEFT JOIN B b ON a.branch_id = b.branch_id
WHERE a.status = 1
GROUP BY a.id, a.name;
優點:單次掃描 B 表,代碼簡潔。
缺點:無法利用 amount 區間索引,全表掃描,數據量大時慢於多 JOIN。
-- 應用代碼 (Python/Java) 動態構建
ranges = [(1000,5000), (5000,10000), (10000,20000)]
joins = []
selects = []
for i, (lo, hi) in enumerate(ranges):
alias = f"b{i}"
joins.append(f"""
LEFT JOIN (
SELECT branch_id, COUNT(*) cnt
FROM B
WHERE amount >= {lo} AND amount < {hi}
GROUP BY branch_id
) {alias} ON a.branch_id = {alias}.branch_id""")
selects.append(f"COALESCE({alias}.cnt, 0) AS range_{lo}_{hi}")
sql = f"SELECT a.id, a.name, {', '.join(selects)} FROM A a {' '.join(joins)} WHERE a.status=1"
b1、b2...)UPDATE STATISTICS 確保優化器選擇正確計劃多次 LEFT JOIN` 子查詢是處理「同表不同條件橫向聚合」的標準、高效、可維護方案。不要為「代碼重複」犧牲性能——SQL 是聲明式語言,重複的結構反而幫助優化器生成最優計劃。配合區間索引、預聚合、覆蓋索引,可支撐千萬級數據秒級查詢。若區間固定且數據量中等,條件聚合是優雅替代;動態區間建議應用層生成標準 JOIN SQL。