问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

必会!MySQL去重3种方法

创作时间:
作者:
@小白创作中心

必会!MySQL去重3种方法

引用
CSDN
1.
https://m.blog.csdn.net/2401_83384536/article/details/136581751

在数据库操作中,去重是一个非常常见的需求。无论是统计独立访客数(UV),还是获取某个字段的唯一值列表,都需要用到去重操作。本文将介绍MySQL中常用的三种去重方法:distinct、group by和row_number窗口函数,并通过具体示例说明它们的使用场景和特点。

假设我们有一张名为task的表,结构如下:

其中:

  • task_id:任务ID
  • order_id:订单ID
  • start_time:开始时间

我们的目标是计算任务的总数量,但由于task_id存在重复值,因此需要先进行去重处理。

distinct

distinct是最常用的去重方法之一,适用于简单的去重场景。以下是使用distinct计算任务总数的SQL语句:

select count(distinct task_id) task_num
from Task;

需要注意的是,distinct通常效率较低,不适合用于展示去重后的具体值,一般与count函数配合使用来计算条数。当distinct后面有多个字段时,只有当所有字段的值都相同时,才会被认为是重复值。

group by

group by子句也可以实现去重功能,同时还能进行分组统计。以下是使用group by计算任务总数的SQL语句:

select count(task_id) task_num
from (select task_id
      from Task
      group by task_id) tmp;

group by的一个优点是可以处理包含null值的去重场景,而distinct在处理null值时可能会有不同表现。

row_number

在支持窗口函数的SQL方言(如Hive SQL、Oracle等)中,还可以使用row_number窗口函数进行去重。以下是使用row_number计算任务总数的SQL语句:

select count(case when rn=1 then task_id else null end) task_num
from (select task_id
       , row_number() over (partition by task_id order by start_time) rn
   from Task) tmp;

row_number窗口函数通过为每一行分配一个唯一的行号来实现去重,其中partition by用于指定分组字段,order by用于指定组内排序字段。

distinct与group by的对比

为了更好地理解distinctgroup by在去重中的使用差异,我们再来看一个示例表test

-- 下方的分号;用来分隔行
select distinct user_id
from Test;    -- 返回 1; 2
select distinct user_id, user_type
from Test;    -- 返回1, 1; 1, 2; 2, 1
select user_id
from Test
group by user_id;    -- 返回1;  2
select user_id, user_type
from Test
group by user_id, user_type;    -- 返回1, 1; 1, 2; 2, 1
select user_id, user_type
from Test
group by user_id;
-- Hive、Oracle等会报错,mysql可以这样写。
-- 返回1, 1 或 1, 2 ; 2, 1(共两行)。只会对group by后面的字段去重,就是说最后返回的记录数等于上一段sql的记录数,即2条
-- 没有放在group by 后面但是在select中放了的字段,只会返回一条记录(好像通常是第一条,应该是没有规律的)

通过这个示例,我们可以看到distinctgroup by在处理多字段去重时的不同行为。distinct会根据所有字段的组合进行去重,而group by只对指定的字段进行去重,其他字段的值可能会出现随机性。

总结来说,三种去重方法各有优劣:

  • distinct:使用简单,但效率较低,不适合展示具体值
  • group by:功能更强大,可以处理复杂场景,但语法相对复杂
  • row_number:灵活性高,适用于支持窗口函数的数据库,但学习成本较高

选择哪种方法取决于具体的应用场景和数据库支持情况。

© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号