分頁查詢中,GROUP BY 後直接 COUNT(*) 只能得到分組內聚合數,無法獲得「分組數」本身。MySQL 內建 SQL_CALC_FOUND_ROWS + FOUND_ROWS() 機制可高效解決此問題,避免雙查詢開銷。
SELECT SQL_CALC_FOUND_ROWS t3.id, a,bunch,of,other,stuff FROM t1, t2, t3 WHERE (associate t1,t2,and t3 with each other) GROUP BY t3.id LIMIT 10, 20; SELECT FOUND_ROWS() as total_groups;
SQL_CALC_FOUND_ROWS:提示优化器在執行 LIMIT 前計算「無 LIMIT 時的總行數」FOUND_ROWS():返回上一條語句的總行數(忽略 LIMIT)GROUP BY 時,總行數即為分組數| 方案 | SQL 範例 | 缺點 |
|---|---|---|
| 傳統雙查詢 | SELECT COUNT(*) FROM ... GROUP BY col;SELECT * FROM ... GROUP BY col LIMIT m,n; | 兩次全表掃描,高併發下性能差 |
| 優化方案 | SELECT SQL_CALC_FOUND_ROWS ... GROUP BY col LIMIT m,n;SELECT FOUND_ROWS(); | 單次掃描,極低額外開銷 |
MySQL 8.0 前無窗口函數,可用用戶變量模擬:
SET @rownum = 0; SELECT @rownum := @rownum + 1 AS row_num, t.* FROM (SELECT * FROM tbl ORDER BY sort_col) t;
應用場景:需要知道某記錄在排序後的具體位置(如排名、分頁定位)。
-- 統計每組記錄數 SELECT column_id, COUNT(*) AS cnt FROM my_table GROUP BY column_id; -- 多字段分組 SELECT dept_id, job_id, COUNT(*) FROM emp GROUP BY dept_id, job_id;
COUNT(*) OVER() 窗口函數替代SQL_CALC_FOUND_ROWS 在 8.0.17 起標記棄用,未來版本可能移除