SQL去重用DISTINCT或GROUP BY:DISTINCT对整行去重,适合留一条记录;GROUP BY配合聚合函数可按字段分组并取代表值;需保留每组最新行时用ROW_NUMBER()窗口函数。

SQL去重查询核心就两点:用 DISTINCT 去掉重复行,或用 GROUP BY 按字段分组后取代表值。选哪个,取决于你到底想“留一条记录”还是“汇总计算”。
DISTINCT:最直接的去重方式
它作用于整行(严格来说是 SELECT 后面的所有列组合),只要两行在所有选中列上的值完全相同,就只保留其中一行。
- 写法简单:SELECT DISTINCT col1, col2 FROM table_name;
- 注意:DISTINCT 必须紧跟在 SELECT 后面,不能写成 SELECT col1, DISTINCT col2
- 如果只想对某列去重但还要查其他列,DISTINCT 不够用——它会按所有列联合去重,这时得换思路
GROUP BY:带逻辑的去重,适合要“留一个代表”的场景
当你需要按某个字段(比如 user_id)去重,同时还想显示该用户的最新订单时间、最高消费额等信息,就得用 GROUP BY 配合聚合函数。
- 基本结构:SELECT user_id, MAX(order_time), SUM(amount) FROM orders GROUP BY user_id;
- 关键规则:SELECT 后非聚合的字段,必须全部出现在 GROUP BY 子句中
- 常见误区:写 SELECT name, age FROM student GROUP BY name —— 这会报错(除非 SQL 模式允许),因为 age 没参与分组也没聚合
去重 + 排序 + 取最新:用窗口函数更精准
DISTINCT 和 GROUP BY 都没法直接告诉你“每组里哪一行是最新/最全的”。这时候用 ROW_NUMBER() 就很自然:
- 示例:查每个用户最新一条登录记录
- SELECT * FROM (SELECT *, ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY login_time DESC) AS rn FROM logins) t WHERE rn = 1;
- PARTITION BY 相当于分组,ORDER BY 决定组内排序,rn=1 就是每组第一行
基本上就这些。DISTINCT 快速直观,GROUP BY 更有表达力,窗口函数则解决“去重并保特征”的进阶需求。不复杂但容易忽略细节,理清目标再选方法,事半功倍。










