如何在SQL中对多个列同时进行COUNT(DISTINCT)计算?

夏伟君_1282

夏伟君_1282

2026-09-01

802人浏览

原创

mysql 8.0+ 支持 count(distinct col1, col2) 直接统计列组合唯一值对,忽略含 null 的行;旧版及 postgresql、sql server 等需用子查询 select count(*) from (select distinct col1, col2 from t) as _。

如何在sql中对多个列同时进行count(distinct)计算?

MySQL 8.0+ 直接支持多列 COUNT(DISTINCT col1, col2)

MySQL 8.0 及以上版本原生支持 COUNT(DISTINCT col1, col2),它统计的是「列组合的唯一值对」数量。比如 (1,'a') 和 (1,'b') 算两个不同组合,而 (1,'a') 出现两次只算一次。

常见错误是误以为它等价于 COUNT(DISTINCT col1) + COUNT(DISTINCT col2) —— 完全不是一回事,后者是两个独立去重计数之和,语义完全不同。

  • 适用场景:分析联合主键、用户-行为对、时间-设备组合等复合唯一性
  • 注意 NULL 处理:(NULL, 'a') 和 ('a', NULL) 均被视为有效组合,但 (NULL, NULL) 在 MySQL 中会被当作一个唯一值(不是忽略)
  • 性能影响:多列 DISTINCT 会触发临时表 + 排序,大数据量时比单列慢不少,建议在 (col1, col2) 上建联合索引

PostgreSQL 和 SQL Server 不支持多列 COUNT(DISTINCT)

PostgreSQL 报错 ERROR: DISTINCT is not supported for multiple columns in aggregate functions;SQL Server 则直接语法不通过。它们只接受单列或表达式(如 COUNT(DISTINCT col1 || col2)),但拼接有风险。

安全做法是用子查询去重再计数:

SELECT COUNT(*) FROM (SELECT DISTINCT col1, col2 FROM t) AS _

这个写法通用、语义清晰,且各数据库都支持。

  • 别名 AS _ 是惯用写法,避免无意义命名
  • 不能省略子查询别名(PostgreSQL/SQL Server 强制要求)
  • 如果只查一列去重后计数,COUNT(DISTINCT col1) 仍比子查询快,别为了一致性强行统一成子查询

用字符串拼接模拟多列 DISTINCT 要小心边界

有人用 COUNT(DISTINCT col1 || '|' || col2)(PostgreSQL)或 COUNT(DISTINCT CONCAT(col1, '|', col2))(MySQL)来绕过限制,但极易出错:

Soofy
Soofy

一款通过AI对话帮助用户学习语言的在线学习工具,将语言练习融入真实交流场景。

下载
  • 若 col1='a|b' 且 col2='c',拼成 'a|b|c',和 col1='a', col2='b|c' 结果一样 → 假合并
  • NULL 参与拼接时整个结果变 NULL(多数数据库中),导致该行被丢弃,计数偏少
  • 类型隐式转换可能截断或报错,比如 INT 和 TEXT 拼接时长度溢出

除非你 100% 控制数据内容且加了严格校验,否则别碰拼接方案。

需要同时算多个 DISTINCT 组合?别嵌套 COUNT(DISTINCT ...)

想在同一 SELECT 中计算 COUNT(DISTINCT a,b)、COUNT(DISTINCT a,c)、COUNT(DISTINCT b,c)?别试图写成一行——MySQL 8.0 允许,但其他数据库不行;而且可读性差、优化器难生效。

更可靠的做法是用 CTE 或多次子查询并联:

WITH d1 AS (SELECT COUNT(*) c FROM (SELECT DISTINCT a,b FROM t) _),<br>d2 AS (SELECT COUNT(*) c FROM (SELECT DISTINCT a,c FROM t) _),<br>d3 AS (SELECT COUNT(*) c FROM (SELECT DISTINCT b,c FROM t) _) <br>SELECT d1.c AS ab_cnt, d2.c AS ac_cnt, d3.c AS bc_cnt FROM d1, d2, d3

虽然多扫几遍表,但逻辑分层清楚,各数据库兼容,也方便加 WHERE 条件做条件去重统计。

真正容易被忽略的是:当表很大且多个组合涉及不同过滤条件时,应该优先考虑物化中间结果(比如建临时表存 DISTINCT 后的结果),而不是反复全表 DISTINCT 扫描。

相关专题

更多
数据分析工具有哪些
数据分析工具有哪些

数据分析工具有Excel、SQL、Python、R、Tableau、Power BI、SAS、SPSS和MATLAB等。详细介绍:1、Excel,具有强大的计算和数据处理功能;2、SQL,可以进行数据查询、过滤、排序、聚合等操作;3、Python,拥有丰富的数据分析库;4、R,拥有丰富的统计分析库和图形库;5、Tableau,提供了直观易用的用户界面等等。

2023.10.12

4203

8

SQL中distinct的用法
SQL中distinct的用法

SQL中distinct的语法是“SELECT DISTINCT column1, column2,...,FROM table_name;”。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2023.10.27

891

4

SQL中months_between使用方法
SQL中months_between使用方法

在SQL中,MONTHS_BETWEEN 是一个常见的函数,用于计算两个日期之间的月份差。想了解更多SQL的相关内容,可以阅读本专题下面的文章。

2024.02.23

1089

5

SQL出现5120错误解决方法
SQL出现5120错误解决方法

SQL Server错误5120是由于没有足够的权限来访问或操作指定的数据库或文件引起的。想了解更多sql错误的相关内容,可以阅读本专题下面的文章。

2024.03.06

6101

10

sql procedure语法错误解决方法
sql procedure语法错误解决方法

sql procedure语法错误解决办法:1、仔细检查错误消息;2、检查语法规则;3、检查括号和引号;4、检查变量和参数;5、检查关键字和函数;6、逐步调试;7、参考文档和示例。想了解更多语法错误的相关内容,可以阅读本专题下面的文章。

2024.03.06

2963

4

oracle数据库运行sql方法
oracle数据库运行sql方法

运行sql步骤包括:打开sql plus工具并连接到数据库。在提示符下输入sql语句。按enter键运行该语句。查看结果,错误消息或退出sql plus。想了解更多oracle数据库的相关内容,可以阅读本专题下面的文章。

2024.04.07

6060

11

sql中where的含义
sql中where的含义

sql中where子句用于从表中过滤数据,它基于指定条件选择特定的行。想了解更多where的相关内容,可以阅读本专题下面的文章。

2024.04.29

8161

6

sql中删除表的语句是什么
sql中删除表的语句是什么

sql中用于删除表的语句是drop table。语法为drop table table_name;该语句将永久删除指定表的表和数据。想了解更多sql的相关内容,可以阅读本专题下面的文章。

2024.04.29

1110

5

sql中删除一列的命令是什么
sql中删除一列的命令是什么

在sql中,使用alter table语句可以删除一列,语法为:alter table table_name drop column column_name。想了解更多sql的相关内容,可以阅读本专题下面的文章。

2024.04.29

972

5

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
热门推荐
/
最新课程
phpStudy极速入门视频教程
phpStudy极速入门视频教程

共6课时 | 54.6万人学习

独孤九贱(4)_PHP视频教程
独孤九贱(4)_PHP视频教程

共89课时 | 133.4万人学习