在mysql的查询操作中,重复数据会影响统计结果的准确性,groupby作为分组查询的核心语法,天然具备去重的能力,通过合理的字段组合和聚合函数搭配,可以实现不同维度的去重需求。

groupby去重的核心原理
groupby的作用是将查询结果按照指定的一个或多个字段进行分组,相同字段值的行会被归为同一组,最终每组只会返回一条记录,这就实现了去重的效果。需要注意的是,groupby默认会保留每组的第一条记录,若需要获取组内其他信息,需要搭配聚合函数使用。
单字段去重的使用方法
当只需要对单个字段进行去重时,直接在查询语句中添加groupby字段即可,这种方式会保留每个分组的第一条数据。
示例场景
假设有一张用户订单表user_order,表结构如下:
| 字段名 | 类型 | 说明 |
|---|---|---|
| id | int | 订单ID |
| user_id | int | 用户ID |
| order_amount | decimal | 订单金额 |
| create_time | datetime | 创建时间 |
现在需要查询所有下过订单的用户ID,去除重复的用户ID,对应的sql语句如下:
-- 单字段groupby去重,查询所有下过订单的用户ID SELECT user_id FROM user_order GROUP BY user_id;
多字段组合去重
如果需要按照多个字段的组合进行去重,只需要在groupby后面添加多个字段即可,多个字段用逗号分隔,只有当所有指定字段的值都相同时,才会被判定为同一组。
还是以上面的user_order表为例,现在需要查询每个用户每天的订单记录,去除同一用户同一天的重复订单,sql语句如下:
-- 多字段组合去重,查询每个用户每天的订单 SELECT user_id, DATE(create_time) as order_date FROM user_order GROUP BY user_id, DATE(create_time);
搭配聚合函数获取组内信息
groupby去重后,若需要获取组内的其他信息,比如每组的数量、最大值、最小值等,需要搭配聚合函数使用,常用的聚合函数有COUNT()、MAX()、MIN()、SUM()等。
示例:查询每个用户的订单总数和最大订单金额,sql语句如下:
-- 搭配聚合函数获取组内统计信息
SELECT
user_id,
COUNT(id) as order_count,
MAX(order_amount) as max_amount
FROM user_order
GROUP BY user_id;
groupby去重和distinct去重的区别
很多用户会混淆groupby和distinct的去重功能,两者的核心差异如下:
- distinct只能对查询的所有字段组合去重,无法搭配聚合函数做组内统计,而groupby可以灵活搭配聚合函数获取组内信息。
- distinct的语法更简洁,适合简单的单字段或多字段组合去重场景,groupby更适合需要分组统计的场景。
- 在单字段去重时,两者的执行效率差异不大,但多字段复杂场景下groupby的灵活性更高。
distinct单字段去重的示例:
-- distinct单字段去重 SELECT DISTINCT user_id FROM user_order;
使用groupby去重的注意事项
在使用groupby进行去重时,需要注意以下几点:
- groupby后面的字段必须出现在select查询列表中,除非该字段被聚合函数包裹,否则mysql会报错。
- 如果需要筛选分组后的结果,不能使用where子句,而要使用having子句,where是在分组前筛选数据,having是在分组后筛选数据。
- groupby默认会对分组字段进行排序,若不需要排序可以添加
ORDER BY NULL来提升查询效率。
示例:查询订单数大于3的用户ID,使用having筛选:
-- 使用having筛选分组后的结果 SELECT user_id, COUNT(id) as order_count FROM user_order GROUP BY user_id HAVING order_count > 3;