DISTINCT 目的:剔除重复行,只做去重;
GROUP BY 目的:分组,一般用来配合聚合函数做统计。
语义作用不同
DISTINCT
对查询结果集 去除重复行,没有分组统计,只是把一模一样的行只保留 1 条。
sql
-- 取出所有不重复的姓名,只去重,不计算
SELECT DISTINCT name FROM student;
GROUP BY
按指定字段分组 ,相同值归为一组,通常搭配聚合函数(count/sum/max/min)做统计。
sql
-- 按姓名分组,统计每个名字有多少人
SELECT name, COUNT(*) FROM student GROUP BY name;
例如:
-- 1
SELECT DISTINCT name,age FROM student;
-- 2
SELECT name,age FROM student GROUP BY name,age;
两条 SQL查询结果完全一样,但:
1:含义:取出 name+age 组合不重复的行
2:含义:按照 name 和 age 两个字段分组
返回字段规则不同
DISTINCT
写哪些列,就对所有列组合 整体去重。SELECT DISTINCT col1,col2,只有 col1+col2 全部相同才算重复。
GROUP BY
MySQL 严格模式下(ONLY_FULL_GROUP_BY 开启):SELECT 后面只能写分组字段 + 聚合函数,不能随便写其他普通字段。
sql
-- 开启ONLY_FULL_GROUP_BY时,下面这条报错!
SELECT name,age FROM student GROUP BY name;
原因:同一个 name 有多条不同 age,数据库不知道取哪个 age。
执行原理(底层)
两者底层都可能需要排序,某些场景优化器会把 DISTINCT 等价转换成 GROUP BY,但语义不一样:
DISTINCT:排序后,删除重复行GROUP BY:排序后,划分成多个组,每组可以计算聚合结果
当没有聚合函数时:
sql
SELECT name FROM student GROUP BY name;
-- 效果等价于
SELECT DISTINCT name FROM student;
结果一样,但业务含义完全不同。只是刚好结果相同,不代表两个东西一样。
使用场景区分
用 DISTINCT :只想要不重复的数据列表,不需要求和、计数等统计。
例:查询有哪些城市(不需要统计数量)
sql
SELECT DISTINCT city FROM user;
用 GROUP BY :需要分组统计(count、sum、avg 等)
例:查询每个城市有多少用户
sql
SELECT city,COUNT(*) FROM user GROUP BY city;
性能
数据量大时,两者都可能需要文件排序,性能消耗都比较高;
如果字段建立索引,GROUP BY / DISTINCT 都可以利用索引避免排序,速度提升;
COUNT(DISTINCT col):统计该字段不重复值数量,是高频组合。
| 对比项 | DISTINCT | GROUP BY |
|---|---|---|
| 核心目的 | 去除重复记录 | 按字段分组,用于聚合统计 |
| 是否必须聚合函数 | ❌ 不需要 | ✅ 一般搭配聚合函数 |
| 字段限制 | 没有 ONLY_FULL_GROUP_BY 限制 | 严格模式下,select 只能出现分组字段 + 聚合函数 |
| 输出 | 原始去重数据 | 分组后的聚合结果 |
| 无聚合时 | 单纯去重 | 分组,结果和 distinct 一样,但语义是分组 |