SQL去重的三种方法汇总​

举报
lxw1844912514 发表于 2022/03/26 23:18:52 2022/03/26
【摘要】 在使用SQL提数的时候,常会遇到表内有重复值的时候,比如我们想得到 uv (独立访客),就需要做去重。 在 MySQL 中通常是使用 distinct 或 group by子句,但在支持窗口函数的 sql(如Hive SQL、Oracle等等) 中还可以使用 row_number 窗口函数进行去重。 举个栗子,现有这样一张...

在使用SQL提数的时候,常会遇到表内有重复值的时候,比如我们想得到 uv (独立访客),就需要做去重。

在 MySQL 中通常是使用 distinct 或 group by子句,但在支持窗口函数的 sql(如Hive SQL、Oracle等等) 中还可以使用 row_number 窗口函数进行去重。

举个栗子,现有这样一张表 task:

0fa2bd324fe0b96b9159ac586032ce87.png

备注:

  • task_id: 任务id;

  • order_id: 订单id;

  • start_time: 开始时间

注意:一个任务对应多条订单

我们需要求出任务的总数量,因为 task_id 并非唯一的,所以需要去重:

distinct


   
  1. -- 列出 task_id 的所有唯一值(去重后的记录)
  2. -- select distinct task_id
  3. -- from Task;
  4. -- 任务总数
  5. select count(distinct task_id) task_num
  6. from Task;

distinct 通常效率较低。它不适合用来展示去重后具体的值,一般与 count 配合用来计算条数。

distinct 使用中,放在 select 后边,对后面所有的字段的值统一进行去重。比如distinct后面有两个字段,那么 1,1 和 1,2 这两条记录不是重复值 。

group by


   
  1. -- 列出 task_id 的所有唯一值(去重后的记录,null也是值)
  2. -- select task_id
  3. -- from Task
  4. -- group by task_id;
  5. -- 任务总数
  6. select count(task_id) task_num
  7. from (select task_id
  8.       from Task
  9.       group by task_id) tmp;

row_number

row_number 是窗口函数,语法如下:

row_number() over (partition by <用于分组的字段名> order by <用于组内排序的字段名>)

其中 partition by 部分可省略。


   
  1. -- 在支持窗口函数的 sql 中使用
  2. select count(case when rn=1 then task_id else null end) task_num
  3. from (select task_id
  4.        , row_number() over (partition by task_id order by start_time) rn
  5.    from Task) tmp;

此外,再借助一个表 test 来理理 distinct 和 group by 在去重中的使用:

535342754bec1e111a5f0ad40b014590.png

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

文章来源: blog.csdn.net,作者:lxw1844912514,版权归原作者所有,如需转载,请联系作者。

原文链接:blog.csdn.net/lxw1844912514/article/details/121690313

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。