在数据去重时,DISTINCT 和 GROUP BY 都可以实现去重功能,但它们在语义、性能和功能上有重要区别:
1. 基本用法对比
DISTINCT
-- 简单去重
SELECT DISTINCT department, job_title
FROM employees;
-- 与聚合函数结合
SELECT COUNT(DISTINCT department)
FROM employees;
GROUP BY
-- 使用 GROUP BY 实现去重
SELECT department, job_title
FROM employees
GROUP BY department, job_title;
2. 主要区别
| 特性 | DISTINCT | GROUP BY |
|---|---|---|
| 语义 | 明确表示”去重” | 表示”分组”,去重是副作用 |
| 聚合函数 | 不能直接使用(需配合COUNT等) | 必须与聚合函数一起使用才有意义 |
| 排序 | 不保证结果顺序 | 某些数据库隐式排序(如MySQL) |
| 性能 | 通常更简单直接 | 可能需要更多资源 |
| 可读性 | 去重意图更明确 | 可能被误解为需要聚合 |
3. 性能考量
大多数情况下:
- DISTINCT 通常更高效,因为它专注于去重
- 数据库优化器可能将 DISTINCT 转换为 GROUP BY 执行
- 有索引时,两者性能差异很小
特殊场景:
-- GROUP BY 有时更快(当需要同时进行聚合计算时)
SELECT department, COUNT(*)
FROM employees
GROUP BY department;
-- 比 DISTINCT + 子查询通常更快
4. 使用建议
用 DISTINCT 当:
- 只需要简单去重
- 查询意图明确是”去重”
- 不需要聚合计算
- 可读性优先的场景
-- 推荐:清晰表达去重意图
SELECT DISTINCT city FROM customers;
用 GROUP BY 当:
- 需要同时进行聚合计算(COUNT, SUM, AVG等)
- 需要分组后过滤(HAVING子句)
- 需要多级分组
- 数据库优化提示 GROUP BY 更快
-- 推荐:需要聚合时
SELECT city, COUNT(*) as customer_count
FROM customers
GROUP BY city
HAVING COUNT(*) > 10;
5. 实际示例对比
-- 场景1:简单去重 - 两者等效
SELECT DISTINCT category FROM products;
SELECT category FROM products GROUP BY category;
-- 场景2:带聚合 - 只能用 GROUP BY
SELECT category, AVG(price), COUNT(*)
FROM products
GROUP BY category;
-- 场景3:复杂场景 - GROUP BY 更灵活
SELECT department,
COUNT(DISTINCT job_title) as job_types,
AVG(salary) as avg_salary
FROM employees
GROUP BY department
HAVING COUNT(*) > 5;
6. 最佳实践
- 简单去重用 DISTINCT – 语义清晰
- 需要聚合计算用 GROUP BY – 功能更强大
- 检查执行计划 – 大数据量时验证性能
- 保持一致性 – 团队统一规范
- 注意NULL处理 – 两者都将NULL视为相同值
-- 推荐模式
-- 1. 简单去重
SELECT DISTINCT column1, column2 FROM table;
-- 2. 分组统计
SELECT column1, column2, COUNT(*), SUM(value)
FROM table
GROUP BY column1, column2
HAVING COUNT(*) > 1;
总结
- 纯去重用 DISTINCT – 更简洁直观
- 分组+聚合用 GROUP BY – 功能更完整
- 性能差异通常不大,但应实际测试
- 选择时优先考虑代码可读性和查询意图的清晰表达