count(distinct column_name)是最直接去重计数方式,统计非null唯一值个数;旧版mysql(如5.6)不支持会报error 1064,须严格写成count(distinct col),不可漏括号或嵌套where;多列去重用count(distinct a, b),null组合被忽略;group by替代方案行为不同且兼容性差;索引显著影响性能。

COUNT(DISTINCT column_name) 是最直接、最常用的方式,能立刻返回某列中非 NULL 的唯一值个数。它不是先查再去重,而是在聚合阶段跳过重复项,性能好、语义清晰——只要你用的数据库支持(MySQL 5.7+、PostgreSQL、SQL Server、Oracle 都行)。
旧版 MySQL 报错 ERROR 1064 怎么办?
MySQL 5.6 及更早版本不支持 COUNT(DISTINCT column) 语法,写成 COUNT DISTINCT column(漏括号)或 COUNT(DISTINCTcolumn)(缺空格)都会触发该错误。
- 必须严格写成
COUNT(DISTINCT column_name),括号不能省,列名要明确 - 若无法升级 MySQL,可用子查询替代:
SELECT COUNT(*) FROM (SELECT DISTINCT column_name FROM table_name) t,注意别名t不可省(MySQL 8.0+ 强制要求) -
DISTINCT不能和WHERE或ORDER BY嵌套在COUNT()内部,比如COUNT(DISTINCT column WHERE condition)是非法的
多列组合去重计数怎么写?
想统计“用户+商品”这对组合的唯一数量,直接用 COUNT(DISTINCT user_id, product_id) 即可。它计算的是组合层面的唯一性,不是分别去重。
- 语义是“有多少个不同的
(user_id, product_id)对”,不是COUNT(DISTINCT user_id) + COUNT(DISTINCT product_id) - 任一列为
NULL时,整条组合会被忽略(例如(1, NULL)和(1, NULL)不算重复,但也不计入结果) - 若需把
NULL当作有效值参与去重,得先用COALESCE(user_id, -1)替换,否则会被静默丢弃
GROUP BY 能替代 COUNT(DISTINCT) 吗?
可以,但行为不同,且跨数据库兼容性差。
-
SELECT COUNT(*) FROM (SELECT col FROM t GROUP BY col) t在 MySQL 中结果等价,但在 PostgreSQL 或 SQL Server 中会报错,提示col must appear in GROUP BY或缺少聚合函数 - 如果表里有其他字段(如时间戳),你希望“每个
col只取最新一条”,GROUP BY col无法控制选哪行,DISTINCT更不行——这时得用窗口函数,比如ROW_NUMBER() OVER (PARTITION BY col ORDER BY updated_at DESC) - 大数据量下,
GROUP BY子查询可能生成临时表,内存占用比原生COUNT(DISTINCT)更高
user_id 建了索引,COUNT(DISTINCT user_id) 往往能走索引扫描;没索引时,InnoDB 可能触发磁盘临时表 + 文件排序,几百万行就明显卡顿。别只盯着语法,先看执行计划里的 Extra 字段有没有 Using temporary; Using filesort。











