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

------期间感谢微信公众号“有关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. css区分ie8/ie9/ie10/ie11 chrome firefox的代码

    以下是几个主要浏览器的css  hack汇总: 现有css样式为: .class{ color:red; } 判断IE8以上的浏览器才执行的代码/* IE8+ */ .class{ color:red ...

  2. 听《津津乐道》ThinkPad专题节目有感

    自2011年使用Mac以来,就没怎么想过要再换一个windows使用,可是前几天听了<津津乐道>播客节目,主播朱峰讲了ThinkPad的使用经历,这个倒是让我回想起第一次见到IBM电脑时的 ...

  3. spiral matrix 螺旋矩阵

    Given a matrix of m x n elements (m rows, n columns), return all elements of the matrix in spiral or ...

  4. JS判断页面加载是否完成

    document.onreadystatechange = function()  //当页面加载状态改变的时候执行function {  if(document.readyState == &quo ...

  5. RabbitMQ In JAVA 介绍及使用

    介绍: RabbitMQ是开源的消息中间件,它是轻量级的,支持多种消息传递协议,可以部署在分布式和联合配置中,以满足高级别.高可用性需求.并且可在许多操作系统和云环境上运行,并为大多数流行语言提供了广 ...

  6. C#高级编程笔记之第一章:.NET体系结构

    1.1 C#与.NET的关系 C#不能孤立地使用,必须与.NET Framework一起使用一起考虑. (1)C#的体系结构和方法论反映了.NET基础方法论. (2)多数情况下,C#的特定语言功能取决 ...

  7. Java单例模式(Singleton)以及实现

    一. 什么是单例模式 因程序需要,有时我们只需要某个类同时保留一个对象,不希望有更多对象,此时,我们则应考虑单例模式的设计. 二. 单例模式的特点 1. 单例模式只能有一个实例. 2. 单例类必须创建 ...

  8. msql索引

    从网上找了两种解决方案: 最近要给一个表加一个联合唯一索引,但是表中的两个联合健有重复值,导致无法创建: 解决方案一:ignore(会删除重复的记录(重复记录只保留一条,其他的删除),然后建立唯一索引 ...

  9. 使用VirtualBox调试项目踩过的坑

    当我们完成项目后 通常需要做其他系统的测试 例如win10下测试完成后要在win7中测试 这时,安装一个虚拟机是较为明智的选择 本文将讲述在使用虚拟机测试Unity发布的exe(所有的3D文件都适用) ...

  10. PAT1094:The Largest Generation

    1094. The Largest Generation (25) 时间限制 200 ms 内存限制 65536 kB 代码长度限制 16000 B 判题程序 Standard 作者 CHEN, Yu ...