COUNT() 是 MySQL 中最常用的聚合函數,但不同寫法(COUNT(*)、COUNT(col)、COUNT(DISTINCT col))在語意、效能與適用儲存引擎上有顯著差異。本文系統整理用法陷阱、引擎差異與優化技巧。
| 寫法 | 統計對象 | NULL 處理 | 典型用途 |
|---|---|---|---|
COUNT(*) | 所有列(行數) | 包含 NULL 行 | 統計總行數、分頁總筆數 |
COUNT(col) | 指定欄位非 NULL 值 | 忽略 NULL | 統計某欄位有資料的筆數 |
COUNT(DISTINCT col) | 指定欄位去重後非 NULL 值 | 忽略 NULL | 統計唯一值數量(如 UV、唯一用戶數) |
-- 測試資料
id | name | password
1 | name1 | 123456
2 | name2 | 123456
3 | name3 | 123456
4 | name4 | NULL
SELECT COUNT(*) FROM `user`; -- 4
SELECT COUNT(name) FROM `user`; -- 4
SELECT COUNT(password) FROM `user`; -- 3
COUNT(*) 無 WHERE 時極速回傳(O(1))。COUNT(*) 需掃描聚簇索引或次要索引,複雜度 O(N)。-- 每類動物數量
SELECT species, COUNT(*) FROM pet GROUP BY species;
-- 每性別數量(含 NULL)
SELECT sex, COUNT(*) FROM pet GROUP BY sex;
-- 種類+性別雙重分組
SELECT species, sex, COUNT(*) FROM pet GROUP BY species, sex;
-- 篩選後分組
SELECT species, sex, COUNT(*)
FROM pet
WHERE species IN ('dog','cat')
GROUP BY species, sex;
注意:SELECT owner, COUNT(*) FROM pet 缺少 GROUP BY 會報錯 ERROR 1140。
SELECT DISTINCT id, type FROM tbl;
-- 實際語意:id 與 type 組合唯一,非單獨 id 唯一
SELECT id, GROUP_CONCAT(type) FROM tbl GROUP BY idSELECT *, ROW_NUMBER() OVER (PARTITION BY id ORDER BY type) AS rn FROM tbl 後篩選 rn=1SELECT id, type, COUNT(DISTINCT id) FROM tbl GROUP BY id, type(會產生多餘計數欄位)COUNT(col) 全表掃描:若只需總行數且為 MyISAM,用 COUNT(*);InnoDB 大表考慮計數表。COUNT(col):在 col 上建立索引,查詢可走 Index Only Scan。COUNT(DISTINCT col) 大表優化:近似計數用 APPROX_COUNT_DISTINCT()(MySQL 8.0.13+),或預先彙總到維度表。SELECT COUNT(*) 與 SELECT ... LIMIT,避免 SQL_CALC_FOUND_ROWS 造成雙重掃描。理解 COUNT 的語意邊界與引擎特性,是編寫高效 SQL 的基礎功夫。