直接对目标字段分组统计并按计数降序取第一条,是最通用可靠的方式:SELECT column_name, COUNT(*) AS cnt FROM table_name GROUP BY column_name ORDER BY cnt DESC LIMIT 1;多个最高频值需用RANK()窗口函数嵌套查询处理,并注意NULL参与分组及索引优化。

用 GROUP BY + COUNT() 找出频次最高的值
直接对目标字段分组统计,再按计数降序取第一条,是最通用、最可靠的方式。注意不能只靠 COUNT() 而不 GROUP BY,否则会得到整张表的总行数,不是每个值的出现次数。
SELECT column_name, COUNT(*) AS cnt FROM table_name GROUP BY column_name ORDER BY cnt DESC LIMIT 1- MySQL 和 PostgreSQL 都支持
LIMIT 1;SQL Server 要改用TOP 1;SQLite 同样用LIMIT - 如果多个值并列最高频(比如都出现 5 次),这条语句只返回其中一行——这是常见盲点,后面会提到怎么处理
处理并列最高频:用窗口函数 RANK()
当需要返回所有出现次数最多的值(不止一个),就不能依赖 LIMIT 或 TOP,得靠排名。窗口函数 RANK() 对重复计数赋予相同名次,比 ROW_NUMBER() 更合适。
SELECT column_name FROM (SELECT column_name, RANK() OVER (ORDER BY COUNT(*) DESC) AS rnk FROM table_name GROUP BY column_name) t WHERE rnk = 1- 必须嵌套一层子查询,因为窗口函数不能直接出现在
WHERE中 - PostgreSQL、SQL Server、Oracle、MySQL 8.0+ 支持;老版本 MySQL 不行,得用变量模拟,但易出错且不可靠
NULL 值会不会被统计进去?
会,但行为取决于具体数据库和写法。在 GROUP BY column_name 中,所有 NULL 会被归为同一组,COUNT(*) 会把它算作一次出现;但 COUNT(column_name) 会跳过 NULL。
- 如果你不希望
NULL参与竞争“最多”,加WHERE column_name IS NOT NULL - 如果业务上
NULL算有效取值(比如表示“未填写”也是一种状态),那就保留它,但得确认下游是否能接受 - 某些场景下,
GROUP BY对NULL的处理在不同 SQL 方言里略有差异,建议在真实数据上验证
性能关键点:别忘了给字段建索引
对高频查询字段做 GROUP BY,没有索引时可能触发全表扫描,尤其数据量大时延迟明显。索引不是可选项,是必要项。
CREATE INDEX idx_column_name ON table_name (column_name)- 复合索引一般没必要,单列索引已足够加速
GROUP BY和COUNT() - 如果同时有
WHERE条件(比如只查某时间段的数据),考虑联合索引,顺序按过滤条件在前、分组字段在后
EXPLAIN 看一眼执行计划,确认走了索引。没走索引却查几百万行,再短的 SQL 也会卡住。

















