MySQL 8.0+ 支持 COUNT(DISTINCT col1, col2),而 5.7 及更早版本不支持,会报错;PostgreSQL 用 COUNT(DISTINCT (col1, col2)),SQL Server 用子查询 SELECT COUNT() FROM (SELECT DISTINCT col1, col2 FROM t) AS t;最通用兼容写法是 SELECT COUNT() FROM (SELECT 1 FROM t GROUP BY col1, col2) AS _。

MySQL 8.0+ 才支持 COUNT(DISTINCT col1, col2)
直接写 COUNT(DISTINCT col1, col2) 在老版本 MySQL(如 5.7)会报错:ERROR 1241 (21000): Operand should contain 1 column(s)。这是因为旧版只允许对单列或表达式去重计数,不支持多列组合去重。PostgreSQL、SQL Server、Oracle 原生也不支持这种语法——它们要求你显式拼接或用子查询。
替代方案:用 GROUP BY + 子查询统计组合唯一行数
最通用、跨数据库兼容的做法是先按多列分组,再统计分组数:
SELECT COUNT(*) FROM ( SELECT 1 FROM your_table GROUP BY col1, col2 ) AS _
这个写法在所有主流 SQL 引擎中都有效。注意几点:
-
SELECT 1是占位写法,避免无谓字段传输;也可写SELECT NULL - 别名
AS _是必需的(MySQL 要求子查询有别名),其他引擎通常也要求 - 如果表很大,
GROUP BY可能触发临时表和 filesort,建议确保(col1, col2)有联合索引
用字符串拼接模拟 COUNT(DISTINCT col1, col2) 的风险
有人会写 COUNT(DISTINCT CONCAT(col1, '|', col2)),但这有隐患:
- 当
col1='a|b'且col2='c',与col1='a'、col2='b|c'拼接后都是'a|b|c',产生误合并 -
NULL值参与CONCAT会导致整结果为NULL,丢失该组合(可用COALESCE补救,但更复杂) - 字符集/排序规则差异可能影响拼接结果稳定性,尤其在跨库迁移时
PostgreSQL 和 SQL Server 的原生替代写法
PostgreSQL 支持行构造器(row constructor),可直接写:
SELECT COUNT(DISTINCT (col1, col2)) FROM your_table;
注意括号:必须是 (col1, col2)(带外层括号),不是 col1, col2。SQL Server 则需用派生表或 CTE:
SELECT COUNT(*) FROM ( SELECT DISTINCT col1, col2 FROM your_table ) AS t;
这种写法语义清晰,且 SQL Server 优化器通常能高效处理 DISTINCT 下推。
Using temporary; Using filesort——有,就说明组合去重代价高,得靠索引兜底。

















