不等价;DISTINCT对整行去重,GROUP BY按列分组并要求聚合或严格模式,语义、错误行为、性能及兼容性均不同。

DISTINCT 和 GROUP BY 在结果集上是否等价?
多数情况下,DISTINCT 和 GROUP BY 对单列去重返回的结果看起来一样,但语义和行为并不等价。关键区别在于:DISTINCT 是对整个行做唯一性判断,而 GROUP BY 是按指定列分组后,每组只取一行(但若未配合聚合函数,MySQL 5.7+ 默认拒绝执行,PostgreSQL 和 SQL Server 则直接报错)。
常见错误现象:
- 在 MySQL 5.7+ 中写
SELECT a, b FROM t GROUP BY a会报错ERROR 1055,除非sql_mode关闭了ONLY_FULL_GROUP_BY - 用
SELECT DISTINCT a, b FROM t能跑通,但实际是把 (a,b) 当作联合唯一键;而GROUP BY a意图是“每个 a 取一条 b”,但 b 的值不明确——数据库可能随便挑一条,也可能报错
什么时候必须用 GROUP BY 而不能用 DISTINCT?
当你需要在去重基础上附加计算时,GROUP BY 是唯一合法路径。DISTINCT 不支持聚合逻辑,也不能控制“每组保留哪条记录”。
使用场景示例:
- 查每个部门的员工数:
SELECT dept, COUNT(*) FROM emp GROUP BY dept——DISTINCT完全无法替代 - 查每个用户最新一笔订单:
SELECT user_id, MAX(created_at) FROM orders GROUP BY user_id—— 这里MAX()依赖GROUP BY语义 - 想取每组中某字段最大值对应整行数据?那得嵌套或用窗口函数,
DISTINCT更无能为力
性能差异主要出现在哪里?
执行计划层面,两者底层都常走排序或哈希去重,但优化器处理方式不同:MySQL 8.0+ 对 DISTINCT 可能自动改写为 GROUP BY,而 PostgreSQL 通常对二者生成相同计划;但一旦涉及多列、大偏移或索引缺失,差距就暴露出来。
影响性能的关键点:
-
GROUP BY若有匹配的复合索引(如INDEX(a,b)),可避免排序;DISTINCT同样受益,但某些旧版本优化器不会主动利用 - 带
ORDER BY时:SELECT DISTINCT a FROM t ORDER BY a可能复用索引排序;但SELECT a FROM t GROUP BY a ORDER BY a在部分场景下会被强制二次排序 -
大数据量分页(如
LIMIT 10000,20)时,GROUP BY因需完整分组常比DISTINCT更慢,尤其当分组键基数高、内存不足触发磁盘临时表
容易被忽略的兼容性陷阱
不同数据库对 GROUP BY 的宽松程度差异极大,而 DISTINCT 行为相对统一。这导致看似能跑的 SQL,在迁移时突然失败。
典型坑点:
- MySQL 5.7+ 默认开启
ONLY_FULL_GROUP_BY,SELECT a, b FROM t GROUP BY a报错;但 SQLite、旧版 MySQL 或关闭该模式的实例能运行——结果中b值不可控 - PostgreSQL 要求
SELECT列要么在GROUP BY中,要么被聚合函数包裹,否则直接拒绝;DISTINCT没这限制 - SQL Server 不允许
SELECT中出现未分组也未聚合的列,且不支持GROUP BY后跟表达式别名(如GROUP BY col_name AS x),而DISTINCT无此语法约束
真正麻烦的不是语法报错,而是同样 SQL 在不同环境返回不同结果——尤其是 b 值随机取某条记录时,业务逻辑可能悄悄出错。











