sql:数据去重的三种方法(代码片段)

还能坚持 还能坚持     2023-04-09     623

关键词:

1、使用distinct去重

distinct用来查询不重复记录的条数,用count(distinct id)来返回不重复字段的条数。用法注意:

  • distinct【查询字段】,必须放在要查询字段的开头,即放在第一个参数;
  • 只能在SELECT 语句中使用,不能在 INSERT, DELETE, UPDATE 中使用;
  • DISTINCT 表示对后面的所有参数的拼接取不重复的记录,即查出的参数拼接每行记录都是唯一的
  • 不能与all同时使用,默认情况下,查询时返回的就是所有的结果。

distinct支持单列、多列的去重方式。

  • 作用于单列

    • 单列去重的方式简明易懂,即相同值只保留1个。
      select distinct name from A    //对A表的name去重然后显示
      
  • 作用于多列

    • 多列的去重则是根据指定的去重的列信息来进行,即只有所有指定的列信息都相同,才会被认为是重复的信息。
    • 注意,distinct作用于多列的时候只在开头加上即可,并不用每个字段都加上。distinct必须在开头,在中间是不可以的,会报错,`select id,distinct name from A //错误
      select distinct id,name from A   //对A表的id和name去重然后显示
      
  • 配合count使用

    select count(distinct name) from A  //对A表的不同的name进行计数
    
  • 按顺序去重时,order by 的列必须出现在 distinct 中

    • 出错代码

    • 改正后的代码

    • 讨论:若不使用Distinct关键字,则order by后面的字段不一定要放在seletc中

MySQL中使用去重distinct方法的示例详解
【Hive】数据去重


2、使用group by

GROUP BY 语句根据一个或多个列对结果集进行分组。在分组的列上我们可以使用 COUNT, SUM, AVG,等函数,形式为select 重复的字段名 from 表名 group by 重复的字段名;

  • group by 对age查询结果进行了分组,自动将重复的项归结为一组。
  • 还可以使用count函数,统计重复的数据有多少个

3、使用ROW_NUMBER() OVERGROUP BY 和 COLLECT_SET/COLLECT_LIST

说到要去重,自然会想到 DISTINCT,但是在 Hive SQL 里,它有两个问题:

  • DISTINCT 会以 SELECT 出的全部列作为 key 进行去重。也就是说,只要有一列的数据不同,DISTINCT 就认为是不同数据而保留。
  • DISTINCT 会将全部数据打到一个 reducer 上执行,造成严重的数据倾斜,耗时巨大。

2.1 ROW_NUMBER() OVER

DISTINCT 的两个问题,用 ROW_NUMBER() OVER 可解。比如,如果我们要按 key1 和 key2 两列为 key 去重,就会写出这样的代码:

WITH temp_table AS (
  SELECT
    key1,
    key2,
    [columns]...,
    ROW_NUMBER() OVER (
      PARTITION BY key1, key2
      ORDER BY column ASC
    ) AS rn
  FROM
    table
)

SELECT
  key1,
  key2,
  [columns]...
FROM
  temp_table
WHERE
  rn = 1;

这样,Hive 会按 key1 和 key2 为 key,将数据打到不同的 mapper 上,然后对 key1 和 key2 都相同的一组数据,按 column 升序排列,并最终在每组中保留排列后的第一条数据。借此就完成了按 key1 和 key2 两列为 key 的去重任务。注意 PARTITION BY 在此起到的作用:

  • 一是按 key1 和 key2 打散数据,解决上述问题 (2);
  • 二是与 ORDER BY 和 rn = 1 的条件结合,按 key1 和 key2 对数据进行分组去重,解决上述问题 (1)。

但显然,这样做十分不优雅(not-elegant),并且不难想见其效率比较低。

row_number() OVER (PARTITION BY COL1 ORDER BY COL2) as num 表示根据 COL1分组,在分组内部根据 COL2排序,此函数计算的值num就表示每组内部排序后的顺序编号(组内连续的唯一的)

2.2 GROUP BY 和 COLLECT_SET/COLLECT_LIST

ROW_NUMBER() OVER 解法的一个核心是利用 PARTITION BY 对数据按 key 分组,同样的功能用 GROUP BY 也可以实现。但是,GROUP BY 需要与聚合函数搭配使用。我们需要考虑,什么样的聚合函数能实现或者间接实现这样的功能呢?不难想到有 COLLECT_SET 和 COLLECT_LIST。

SELECT
  key1,
  key2,
  [COLLECT_LIST(column)[1] AS column]...
FROM
  temp_table
GROUP BY
  key1, key2

对于 key1 和 key2 以外的列,我们用 COLLECT_LIST 将他们收集起来,然后输出第一个收集进来的结果。这里使用 COLLECT_LIST 而非 COLLECT_SET 的原因在于 SET 内是无序的,因此你无法保证输出的 columns 都来自同一条数据。若对于此没有要求或限制,则可以使用 COLLECT_SET,它会更节省资源。

相比前一种办法,由于省略了排序和(可能的)落盘动作,所以效率会高不少。但是因为(可能)不落盘,所以 COLLECT_LIST 中的数据都会缓存在内存当中。如果重复数量特别大,这种方法可能会触发 OOM。此时应考虑将数据进一步打散,然后再合并;或者干脆换用前一种办法。

删除 Hive SQL 查询结果中的重复内容


数据库之MySQL查询去重数据

sql:数据去重的三种方法(代码片段)

1、使用distinct去重distinct用来查询不重复记录的条数,用count(distinctid)来返回不重复字段的条数。用法注意:distinct【查询字段】,必须放在要查询字段的开头,即放在第一个参数;只能在SELECT语句中使用,... 查看详情

数组去重的三种方法

这篇文章是参考http://www.jb51.net/article/46154.htm1.最基本的去重方法思路:定义一个新数组,并存放原数组的第一个元素,然后将元素组一一和新数组的元素对比,若不同则存放在新数组中。functionunique(arr){  varres=[arr[0]];  for(va... 查看详情

数组去重的三种方法

//1.遍历数组法,通过indexOf检索临时新建的数组,检索值为arr数组里面的值,没有则加入新建数组vararr=[1,4,3,5,1,2,5,4,3,2,1,4,2,6];varn=[];for(vari=0;i<arr.length;i++){if(n.indexOf(arr[i])==-1){n.push(arr[i]);}n.sort(functionsortNumber(a,b 查看详情

set/...去重的方法(代码片段)

在ES6中,引入了一个新的数据结构类型:Set。而Set与Array的结构是很类似的,且Set和Array可以相互进行转换。Set对象允许你存储任何类型的唯一值,无论是原始值或者是对象引用。...扩展运算符ES6的去重:arr=[2,2,2,5]arr=[...newSet(arr)... 查看详情

刷题|数组去重的4种方法引发的思考

...数组的重复项,有boolundefinednullNaNnumberobjectstring几乎所有数据类型  但是去重的时候,不要求去除object"{}"这个考点有两个一个indexOf 和 NaN!==NaN  这种去重,有三种解决方案  使用indexOf  原代码  Array.prototype.che... 查看详情

数组去重的6种方法(代码片段)

数组去重常见方法利用Setconstarr=[1,2,1,'3','3',true,true,,]Array.from(newSet(arr))//[1,2,'3',true,,]利用splice()方法constarr=[1,2,1,'3','3',true,true,,]co 查看详情

数组去重的6种方法(代码片段)

数组去重常见方法利用Setconstarr=[1,2,1,'3','3',true,true,,]Array.from(newSet(arr))//[1,2,'3',true,,]利用splice()方法constarr=[1,2,1,'3','3',true,true,,]constremoveDup 查看详情

数组去重的方法(代码片段)

 方法一:利用functionarrRepeat(arr)letobj=;letnewArray=[];for(leti=0;i<arr.length;i++)if(!obj.hasOwnProperty(arr[i]))obj[arr[i]]=i;newArray.push(arr[i]);returnnewArrayconsole.log(arrRepeat([ 查看详情

原创mybatisplus调用原生sql的三种方法(代码片段)

前言在有些情况下需要用到MybatisPlus查询原生SQL,MybatisPlus其实带有运行原生SQL的方法,我这里列举三种方法一这也是网上流传最广的方法,但是我个人认为这个方法并不优雅,且采用$的方式代码审计可能会无法... 查看详情

七种去重的方法(代码片段)

1<script>2vararr=[6,2,2,4,4,6,6,4,4,6,6,2,23,23,31];3/*第一种去重方式:双重循环*/4/*functionToheavy(arr)5if(!Array.isArray(arr))6return"typeerror!";78letnewarr=[];9for(leti=0;i<arr.length;i++)10letfl 查看详情

js对象数组操作之一:对象数组中对象去重的方法总结(代码片段)

...业务中,经常会有一个数组由多个对象构成,需要对这种数据结构进行操作,如下:constarr=[name:‘tom‘,age:15,name:‘jack‘,age:18,name:‘tom‘,age:10,...]今天总结了一下先说这种数据结构的去重方法,对于数组中的多个对象去除重复,... 查看详情

关于sql去重的几种方法

...重复量低时,DISTINCT就比GROUPBY快一点了,而如果随着整体数据量的增加,效果会越来越明显。 查看详情

一个对象,数组去重的方法(代码片段)

对象:unique1(array)//数组去重varallArr=[];//新数组for(vari=0;i<array.length;i++)varflag=true;  for(varj=0;j<allArr.length;j++)if(array[i].cityId==allArr[j].cityId)     flag=false;    ;  ;  if(flag) 查看详情

list去重的6种方法,这种方法最完美!(代码片段)

...常的业务开发中,偶尔会遇到需要将List集合中的重复数据去除掉的场景。这个时候可能有同学会问:为什么不直接使用Set或者LinkedHashSet呢?这样不就没有重复数据的问题了嘛?​不得不说,能提这个问题的同... 查看详情

js数组去重的六种方法(代码片段)

一、利用ES6Set去重(ES6中最常用)functionunique(arr)returnArray.from(newSet(arr))vararr=[1,1,‘true‘,‘true‘,true,true,15,15,false,false,undefined,undefined,null,null,NaN,NaN,‘NaN‘,0,0,‘a‘,‘a‘,,];console.log( 查看详情

数组去重的五种方法(代码片段)

1.第一种方式就是最简单的set去重(o(n))vararr=[1,2,2,4,3,4,1,3,2,7,5,6,1]varnewArr=newSet(arr)2.第二种方式就是用indexOf来去重(o(n^3))判断新数组中某个数字是否存在functionfn(arr)letnewArr=[]arr.forEach((val)=>if(newArr.indexOf(val)==-1)newArr.push(val))returnnewA... 查看详情

细说mysql创建表的三种方法(代码片段)

...只谈技术不剪发的Tony老师。SQL标准使用CREATETABLE语句创建数据表;MySQL则实现了三种创建表的方法,支持自定义表结构或者通过复制已有的表结构来创建新表,本文给大家分别介绍一下这些方法的使用和注意事项。如... 查看详情

js数组去重的几种方法(代码片段)

数组去重1双层for循环(类似冒泡排序的双层循环写法)vararr=[2,3,4,2,34,21,1,12,3,4,1]for(vari=0;i<arr.length;i++)//第一层:每次循环拿到arr中一个元素 for(varj=i+1;j<arr.length;j++) 查看详情