如果数据表没有做好约束,那么数据库中难免会遇到数据重复的情况。今天就遇到这么个看起来简单却又费神的问题---如何去重。

------期间感谢微信公众号“有关SQL”的博主大牛提供的指导和建议。大家可以关注下他的公众号。

借鉴下大神的思路,去除重复的核心思想就两个:

1:找到重复记录,删除他们;

2:找到非重复记录,保留他们

两个思想,操作方式不同,取决于重复记录与非重复记录的行数倾斜度。

情况一:数据表本身数据量不大的情况,如何去除重复

一:创建测试表

CREATE TABLE test(id INT ,NAME VARCHAR(20))

二:插入数据

INSERT INTO test VALUES (1,'001')
INSERT INTO test VALUES (2,'002')
INSERT INTO test VALUES (3,'003')
INSERT INTO test VALUES (3,'003')
INSERT INTO test VALUES (3,'003')
INSERT INTO test VALUES (3,'003')

 刚开始用SQL的开窗函数对数据行进行排序

SELECT t.id,t.NAME,row_number() OVER (partition by t.id ORDER BY t.id ) AS NUM FROM test AS t

效果如下:

然后发现其实并没有什么用,跟源表无法匹配关联起来,准确的删除4行重复记录里的3行记录。想来想去,唯有强大的游标才能帮到我,因为游标是对数据逐行操作的!!!

想到这点后,咋们说做就做:

三:游标代码

 declare @max int,@id int
declare cur_rows cursor local for select id,count(*) from test group by id having count(*) > 1
open cur_rows
fetch cur_rows into @id,@max
while @@fetch_status=0
begin
select @max = @max -1
set rowcount @max
delete from test where id= @id
fetch cur_rows into @id,@max
end
close cur_rows
set rowcount 0

最后效果:

当然,如果只有悉数的几种重复数据行,你也可以这样玩

 CREATE TABLE #table1  (id INT,NAME VARCHAR(20),COT1 INT,DEL int )--创建临时表

 INSERT INTO #table1--将重复行的信息以及重复行数存放到临时表
SELECT DISTINCT
t.id,t.NAME,t.COT1,t.COT1-1
FROM
(SELECT id,NAME,COUNT(*)OVER (PARTITION BY id) AS COT1 FROM test) AS t
WHERE t.COT1>1

效果如图:

随后执行删除语句:

 DELETE TOP (4) a FROM  test AS a WHERE a.id=3

也可达到效果。

情况二:数据表数据量超大,如何去除重复

如果原表重复记录太多,删掉他们肯定费事费时。

delete 操作既要寻址,还要写 Log ,造成锁表时间太长,影响并发。

那么将这些非重复记录先取出来,放入新表,整理完毕后,丢弃原表,重命名新表为原表名即可;

如果非重复记录很多,将他们取出来就又要花很长时间了,设想 1 亿的数据量导出来,不现实了吧。那么只有保留他们,而将重复记录删掉即可。

这里假设数据表数据量很大,已经达到千万级别甚至过亿数量级别情况下的做法(将重复数据取出,整理后导回源表):

1:将重复数据取出

SELECT
DISTINCT id,NAME
INTO #TEMP
FROM
(
SELECT
id,NAME,
ROW_NUMBER()OVER(PARTITION BY id ORDER BY NAME ASC) AS RNK
FROM Test WITH(NOLOCK)
) TMP
WHERE RNK>1

2:删除源表中所有重复记录(暂时不保留)

WHILE (EXISTS(SELECT TOP 1 1 FROM Test ts INNER JOIN #TEMP TP ON TP.id = ts.id ))
BEGIN
DELETE TOP (10000) Test
FROM Test
INNER JOIN #TEMP TP ON Test.id = TP.id
END

3:将临时表中存储的备份数据,插回源表(单行数据)

INSERT INTO Test(id,NAME) 

最后彻底删除临时中间表

DROP TABLE #TEMP

其中需要注意的是:

a:具体操作中尽量使用实体表,这里中间表只是方便演示;

b:使用while和delete top 的目的是为了保证一个事务足够小,不至于日志爆表;

SQL 中如何删除重复(每列数据都重复)的记录,只保留一行?的更多相关文章

  1. SQL中删除重复的行(重复数据),只保留一行 转

    方法一:使用在T-SQL的编程中 分配一个列号码,以COL1,COL2组合来分区排序,删除DATABASE重复的行(重复数据),只保留一行 // COL1,COL2是数据库DATABASE的栏位 de ...

  2. SQL中批量删除被注入的恶意代码的方法

    下文将为您介绍SQL中批量删除被注入的恶意代码的方法,供您参考,如果您也遇到了这样的问题,不妨一看,相信对您会有所帮助. 1,如果你的数据表很少的话,那么写几条简单的sql就搞定了 对于表中的nvch ...

  3. 如何在EXCEL中找出第一列中不包含的第二列数据

    1.找出第一列中不包含的第二列数据:=IFERROR(VLOOKUP(A:A,B:B,1,0),"无") 2.A列相同,B列相加:=SUMIF(G:G,G1,J:J)

  4. mysql 去除重复 Select中DISTINCT关键字的用法 在使用mysql时,有时需要查询出某个字段不重复的记录,虽然mysql提供 有distinct这个关键字来过滤掉多余的重复记录只保留一条,但往往只用它来返回不重复记录的条数,而不是用它来返回不重记录的所有值。其原因是 distinct只能返回它的目标字段,而无法返回其它字段,这个问题让我困扰了很久,用distinct不能解决的话,

      在使用mysql时,有时需要查询出某个字段不重复的记录,虽然mysql提供 有distinct这个关键字来过滤掉多余的重复记录只保留一条,但往往只用它来返回不重复记录的条数,而不是用它来返回不重记 ...

  5. MSSQL sql server 2005/2008 row_number()函数应用之–删除表中重复记录,只保留一条不重复数据

    转自:http://www.maomao365.com/?p=4942 下文主要讲述:重复数据只获取一条的方法 row_number函数在数据库中的功能是为每一行 按照一定的规则生成一个编号,我们常常 ...

  6. 【转】SQL删除重复记录,只保留其中一条

    SQL:删除重复数据,只保留一条用SQL语句,删除掉重复项只保留一条在几千条记录里,存在着些相同的记录,如何能用SQL语句,删除掉重复的呢 1.查找表中多余的重复记录,重复记录是根据单个字段(peop ...

  7. SQL删除重复的记录(只保留一条)

    首先新建表: --创建示例表 CREATE TABLE t ( id ,) PRIMARY KEY, a ), b ) ) --插入数据 INSERT INTO t SELECT 'aa','bb' ...

  8. SQL中一次插入多条数据

    SQL中insert一次可以插入一条数据,我们有三种方法可以一次性插入多条数据. 1. 语法:select 字段列表 into 新表 from 源表 注意事项:此种方法新表是系统自动创建,语句执行前不 ...

  9. SQL SERVER 实现分组合并实现列数据拼接

    需求场景: SQL SERVER 中组织的数据结构是一个层级关系,现在需要抓出每个组织节点以上的全部组织信息,数据示例如下: ADOrg_ID--------------ParentID------- ...

随机推荐

  1. python22期第一天(课程总结)

    1.Python介绍: python是一门高级编程语言,涉及领域比较广泛,社区活跃,由一个核心开发团队在维护,相对其他语言,易于学习,可移植性强,可扩展性强,易于维护,有大量的标准库可供使用. 2.P ...

  2. springMVC中添加restful 风格

    RESTful架构:是一种设计的风格,并不是标准,只是提供了一组设计原则和约束条件,也是目前比较流行的一种互联网软件架构.它结构清晰.符合标准.易于理解.扩展方便,所以正得到越来越多网站的采用. 关于 ...

  3. 关于JavaScript的那些话

    1.初学者动手环境----推荐Chrome的控制台(F12调用)2.JS中两个非常重要的数据类型是对象和数组.3.JavaScript 程序是用Unicode字符集编写的.4.JavaScript是区 ...

  4. [INet] WebSocket 协议中的数据收发过程

    WebSocket 和 HTTP 相似,只是一个应用层协议,对下层透明,所以不涉及 TCP/IP. 由于浏览器支持了 WebSocket,所以在用 JS 写客户端的时候,是无需考虑数据的编码解码的. ...

  5. 部署网站: 配置项目到iis上运行报目录错误

    配置项目到iis上运行报目录错误 以下三种方法可使用: 1.添加文件访问权限 everyone  (线上环境慎用) 2.重新注册iis 3.web.config 加一段话 在<system.we ...

  6. jdk和tomcat环境配置

    一.安装JDK和Tomcat 1,安装JDK:直接运行jdk-7-windows-i586.exe可执行程序,默认安装即可. 备注:路径可以其他盘符,不建议路径包含中文名及特殊符号. 2.安装Tomc ...

  7. ArcCore重构-头文件引用问题的初步解决

    基于官方arc-stable-9c57d86f66be,AUTOSAR版本3.1.5   基本问题 1. 头文件引用混乱,所有头文件通过从搜索路径(-I)中引用,存在名称污染问题,需加入路径信息:   ...

  8. C++ 利用流来进行string和其他类的转换

    通过这种方法可以实现任意转换,需要头文件 #include<string> #include<sstream> 期中sstream提供了我们的主角string流,下面给出int ...

  9. QT窗体的小技巧

    1.界面透明 setWindowOpacity(0.8);//构造函数中加此句,1为不透明,0为完全透明,0.8为80%不透明. 2.设置背景图片 QPixmap pixmap = QPixmap(& ...

  10. NetCore版RPC框架NewLife.ApiServer

    微服务和消息队列的基础都是RPC框架,比较有名的有WCF.gRPC.Dubbo等,我们的NewLife.ApiServer建立在网络库NewLife.Net之上,支持.Net Core,追求轻量级和高 ...