在SQL查询的实际开发中,经常需要从表中提取某一列或多列的不重复值,常见实现方式有两种,分别是使用DISTINCT关键字和GROUP BY分组语句。两种方式都能达成去重目标,但适用场景和底层逻辑有所不同,需要根据实际需求选择。

DISTINCT的基本用法
DISTINCT是SQL中专门用于去重的关键字,直接作用于SELECT后面的字段,会对查询结果中所有选中字段的组合进行去重,保留完全不重复的记录行。
单字段去重示例
假设有一张用户表user,其中包含city字段,需要获取所有不重复的城市名称,语法如下:
-- 查询user表中所有不重复的城市 SELECT DISTINCT city FROM user;
多字段去重示例
如果需要同时获取不重复的省份和城市组合,可以对多个字段使用DISTINCT:
-- 查询不重复的省份+城市组合 SELECT DISTINCT province, city FROM user;
GROUP BY的基本用法
GROUP BY的核心作用是对数据进行分组聚合,当仅对字段进行分组而不使用聚合函数时,也能实现去重效果,每个分组只会保留一条记录。
单字段去重示例
同样获取user表中不重复的城市名称,使用GROUP BY的写法如下:
-- 使用GROUP BY查询不重复的城市 SELECT city FROM user GROUP BY city;
多字段去重示例
获取不重复的省份和城市组合:
-- 使用GROUP BY查询不重复的省份+城市组合 SELECT province, city FROM user GROUP BY province, city;
DISTINCT与GROUP BY的差异对比
两种方式虽然都能实现去重,但在多个维度存在区别,具体对比如下:
| 对比维度 | DISTINCT | GROUP BY |
|---|---|---|
| 核心定位 | 专门用于去重的关键字 | 分组聚合工具,去重是附带效果 |
| 聚合函数支持 | 不能直接搭配聚合函数使用 | 可以搭配COUNT、SUM等聚合函数使用 |
| 排序特性 | 部分数据库下会默认对结果排序 | 默认不对结果排序,需要手动加ORDER BY |
| 适用场景 | 仅需获取不重复值,无额外统计需求 | 去重的同时需要统计每组数据的数量或其他聚合指标 |
性能与选择建议
在大多数数据库引擎中,仅进行简单去重时,DISTINCT和GROUP BY的执行计划基本一致,性能差异可以忽略。但如果需要同时统计每组的记录数,优先选择GROUP BY,因为可以直接搭配COUNT函数:
-- 查询每个城市对应的用户数量,同时去重城市 SELECT city, COUNT(*) AS user_count FROM user GROUP BY city;
如果只需要获取不重复值,没有统计需求,使用DISTINCT语义更清晰,代码可读性更高。需要注意,DISTINCT会对所有选中字段的组合去重,不要误以为仅对第一个字段去重。另外,对包含NULL值的字段使用去重时,NULL会被视为一个独立的重复值组,最终会保留一条NULL记录。
注意:不要在DISTINCT后面加括号包裹字段,比如DISTINCT (city)是错误写法,正确写法为DISTINCT city。
常见使用误区
- 误以为DISTINCT可以单独对某个字段去重,而忽略其他选中字段,实际上DISTINCT作用于所有选中字段的组合
- 在不需要聚合的场景下强行使用GROUP BY,导致代码冗余,可读性下降
- 对大表去重时,没有在去重字段上建立索引,导致全表扫描,查询效率低下
根据实际业务需求选择合适的方式,既能保证查询逻辑清晰,也能获得更好的执行效率。如果后续需要对去重后的结果做进一步筛选,两种方式都可以在外层嵌套查询或者使用HAVING子句(GROUP BY场景)实现。