SQL去重需按业务需求选择方法:纯值去重用DISTINCT,按维度取最新记录用ROW_NUMBER()窗口函数,合并多行数据用GROUP BY配合STRING_AGG等聚合函数。

SQL去重不是简单加个 DISTINCT 就完事——它得看你要去重的维度、是否保留其他字段、要不要最新/最全记录,甚至还要考虑性能和业务逻辑。下面用几个真实场景讲清楚怎么选对方法。
基础去重:只取唯一值,不关心哪一条
最常见需求:查出所有不重复的部门名称、城市、产品类别等。
- 直接用 SELECT DISTINCT 列名,简单高效
- 注意:DISTINCT 作用于整行结果,如果 SELECT 多列,只要组合值相同就会被去重
- 错误示范:SELECT DISTINCT dept_name, hire_date FROM emp —— 可能返回同一部门多条记录(因入职时间不同),这不是你想要的“按部门去重”
按某列去重,但要保留完整信息(比如每部门最新一条员工)
这时候 DISTINCT 不够用了,得靠窗口函数或关联子查询。
- 推荐用 ROW_NUMBER() OVER (PARTITION BY 部门 ORDER BY 入职日期 DESC) 标序号,再外层筛选 rn = 1
- 示例:SELECT * FROM (SELECT *, ROW_NUMBER() OVER (PARTITION BY dept_id ORDER BY updated_at DESC) AS rn FROM employees) t WHERE t.rn = 1
- 替代方案:用 GROUP BY + 聚合函数(如 MAX(id)),再连表查原记录——适合主键明确、逻辑清晰的场景
去重同时要统计或合并数据(如合并同一用户的多条标签)
不是删记录,而是把重复维度下的多行聚合成一行。
- 用 GROUP BY + STRING_AGG(PostgreSQL)、GROUP_CONCAT(MySQL)、STRING_AGG(SQL Server 2017+)
- 例如:把用户所有兴趣标签拼成逗号分隔字符串:SELECT user_id, STRING_AGG(interest, ', ') FROM user_interests GROUP BY user_id
- 注意 NULL 处理和去重嵌套(如先 DISTINCT 再聚合):部分数据库支持 STRING_AGG(DISTINCT interest, ', ')
误删风险高?先验证,再操作
真正删数据前,务必确认哪些行会被影响。
- 先运行 SELECT COUNT(*) 和 COUNT(DISTINCT xxx) 对比,看重复比例
- 用 GROUP BY + HAVING COUNT(*) > 1 查出具体重复组:SELECT email, COUNT(*) FROM users GROUP BY email HAVING COUNT(*) > 1
- 删数据别直接 DELETE FROM table;建议用临时表存要保留的ID,或加事务 + LIMIT 测试
基本上就这些。去重本质是明确“以什么为单位算重复”,再匹配工具:纯值用 DISTINCT,带逻辑用窗口函数,要聚合用 GROUP BY。别硬套模板,先想清楚业务含义。
以上就是SQL去重查询怎么实现_真实案例解析强化复杂查询思维【教学】的详细内容,更多请关注php中文网其它相关文章!