T-SQL技术收集——删除重复数据
在工作和面试中,经常出现如何查询或者删除重复数据的问题,如果有主键,那还好办一点,如果没有主键,那就有点麻烦。
当一个表上没有辅助键时,如果使用SSMS界面来删除,就会报错(注意,本人测试环境是2012,所以界面可能会有所不一样,但是对结果没有任何影响):

因为在创建表后插入数据是没有做判断。但是在删除时,为了保证数据库的一致性,RDBMS还是会做判断从而拒绝执行这类操作。
说明:
要解决这种问题,除了在设计的过程中做好之外,还可以在数据没有重复数据的情况下,使用ALTER TABLE ADD Constraint语句来增加约束。
但是要删除现有的重复值,使用SSMS界面是无法实现的,就算能实现,当数据量到达一定程度,也是不现实的。此时只能使用T-SQL语句,搭配SET ROWCOUNT 1让数据的处理方式一次一行或这使用DELETE TOP (1)的方式删除,注意,括号是必须的。
SET ROWCOUNT { number | @number_var }:使 SQL Server 在返回指定的行数之后停止处理查询。如果需要取消限制,只需要使用SETROWCOUNT 0就可以。
下面是例子:
--使用set rowcount 3设定,查询所有数据
SET
ROWCOUNT 3
SELECT
* FROM
AdventureWorks.HumanResources.Department
行
结果如下:

--使用set rowcount 3,修改所有数据
UPDATE
AdventureWorks.HumanResources.Department
SET
name=name
(3 行受影响)
--回复原有设置
SET
ROWCOUNT 0
最后使用TOP (N)设定搭配INSERT/UPDATE /DELETE ,注意这部分只适合2005以后。
--使用TOP(3)设置,查询所有数据,注意是要有括号的
SELECT
TOP(3)
* FROM
AdventureWorks.HumanResources.Department
行

UPDATE
TOP(3)
AdventureWorks.HumanResources.Department
SET name
=name
(3 行受影响)
另外,SQLServer提供了一个系统函数@@ROWCOUNT来返回影响行数。以下是例子:
--使用@@rowcount系统函数返回影响行数
SELECT
EmployeeID,Title
FROM
AdventureWorks.HumanResources.Employee
WHERE
Title LIKE
'%Manager%'
GO
SELECT
@@ROWCOUNT 'Result'

解决方法:
首先创建一个测试表和插入测试数据:
USE tempdb
GO
CREATE TABLE
MyT(
[SID]
INT,sname
VARCHAR(10),sdt
DATETIME)
GO
--插入测试数据
INSERT INTO
MyT VALUES (1,'Lu','2012/01/01');INSERT INTO
MyT VALUES (1,'Lu','2012/07/08');INSERT INTO
MyT VALUES (1,'Lu','2012/04/03');INSERT INTO
MyT VALUES (2,'Tian','2012/03/01');INSERT INTO
MyT VALUES (2,'Tian','2012/05/09');INSERT INTO
MyT VALUES (2,'Tian','2012/01/01');INSERT INTO
MyT VALUES (3,'AD','2012/01/08');INSERT INTO
MyT VALUES (3,'AD','2012/03/01');INSERT INTO
MyT VALUES (4,'Sun','2012/02/01');INSERT INTO
MyT VALUES (1,'Lu','2012/01/01');INSERT INTO
MyT VALUES (1,'Lu','2012/07/08');INSERT INTO
MyT VALUES (1,'Lu','2012/04/03');INSERT INTO
MyT VALUES (2,'Tian','2012/03/01');INSERT INTO
MyT VALUES (2,'Tian','2012/05/09');INSERT INTO
MyT VALUES (2,'Tian','2012/01/01');INSERT INTO
MyT VALUES (3,'AD','2012/01/08');INSERT INTO
MyT VALUES (3,'AD','2012/03/01');INSERT INTO
MyT VALUES (4,'Sun','2012/02/01');
GO
第一种方法:
使用SET ROWCOUNT 1方法来删除重复数据:
需要搭配WHILE 1=1无限循环,搭配BREAK作为终止。针对找出来的重复数据,使用GROUP BY 和HAVING COUNT(1)>1作为筛选条件,可以避免所有数据被删除。
SET ROWCOUNT 1
WHILE 1=1
BEGIN
DELETE
FROM MyTWHERE
[sid] IN(
SELECT
[sid] FROM MyTGROUP
BY [sid],snameHAVING
COUNT(1)>1)
IF
@@ROWCOUNT=0BREAK
END
SET ROWCOUNT 0
--可以发现,重复的数据已经删除
SELECT *
FROM MyT
第二种方法:
使用DELETE TOP(N)方法,先把刚才插入测试数据的脚本再执行,可以多执行几次。DELETE TOP(1)可以用来替代SET ROWCOUNT 1:
WHILE 1=1
BEGIN
DELETE
TOP(1)
FROM MyTWHERE
[sid] IN(
SELECT
[sid] FROM MyTGROUP
BY [sid],snameHAVING
COUNT(1)>1)
IF
@@ROWCOUNT=0BREAK
END
结果和上面的一样。
扩充:保留最近的一行数据:
有时候不仅仅要去掉重复数据,也要保证剩下的是最新的数据(日期最大),此时可以借助索引,使用索引排序,然后把日期最小的那些删掉,只保留日期最大的那一笔。
--建立复合索引,利用索引将数据以编号和日期升序排序
CREATE INDEX
IDX_DT ON
MyT([sid],sdt
ASC)GO
--修改删除语句,搭配with index查询提示
WHILE 1=1
BEGIN
DELETE
TOP(1)
FROM MyTWHERE
[sid] IN(
SELECT
[sid] FROM MyT
WITH (INDEX(idx_dt))GROUP
BY [sid],snameHAVING
COUNT(1)
>1)
IF
@@ROWCOUNT=0BREAK
END
查询结果:
SELECT *
FROM MyT

注意:
为了向后兼容,括号在 SELECT 语句中是可选的。
我们建议您始终对 SELECT 语句中的 TOP 使用括号,这样,就可以与在 INSERT、UPDATE、MERGE 和 DELETE 语句中需要使用括号保持一致(在这种情况下括号是必需的)。
(出自SQL SERVER 2012联机丛书)
T-SQL技术收集——删除重复数据的更多相关文章
- 面试题中经常遇到的SQL题:删除重复数据,保留其中一条
如题,解决思路如下: 1.首先我们需要找出拥有重复数据的记录 ---以name字段分组 select Name,COUNT(Name) as [count] from Permission group ...
- 你真的会玩SQL吗?删除重复数据且只保留一条
在网上看过一些解决方法 我在此给出的方法适用于无唯一ID的情形 表:TB_MACVideoAndPicture 字段只有2个:mac,content mac作为ID,正常情况下mac数据是唯一的,由于 ...
- SQL Server中删除重复数据
delete from A ) )
- SQL表之间复制数据、选出随机几条数据、删除重复数据、取得自增长列等操作
--表之间数据复制 SELECT* INTO yozhu FROM yo --复制一份表 SELECT* INTO yozhu1 FROM yo where 1<>1 --只复制表结构,无 ...
- SQL server 存储过程 C#调用Windows CMD命令并返回输出结果 Mysql删除重复数据保留最小的id C# 取字符串中间文本 取字符串左边 取字符串右边 C# JSON格式数据高级用法
create proc insertLog@Title nvarchar(50),@Contents nvarchar(max),@UserId int,@CreateTime datetimeasi ...
- sql查询删除重复数据
数据库UserInfo 删除重复数据 即删除重复的用户名手机号 同一个用户名手机号只保留一个用户 01.根据多个字段查询重复数据 with data1 as( select MobilePhone,N ...
- sql 删除重复数据且保留其中一条 用sql 关键字:with ROW_NUMBER
--1.建立表:Coursecreate table Course( ID int identity(1,1),--ID Student varchar(20) ,--学生 Sub varchar(2 ...
- SQL语句删除重复数据
1.如表中没有主键,先添加自动增长主键 alter table 表名 add 列名 int identity (1,1) primary key 2.删除重复数据 delete from 表名 whe ...
- SQL:一句话删除重复的数据
--构造原始数据 )) --插入数据 INSERT INTO #T (N)VALUES ('A') --方式一:一句话删除重复数据(无主键) --方式二:采用CTQ,with的写法删除 ;
随机推荐
- Android-IA Power Manager (S3)
Sleep and wake up
- hdu 2082 生成函数
主题链接:http://acm.hdu.edu.cn/showproblem.php?pid=2082 找单词 Time Limit: 1000/1000 MS (Java/Others) Me ...
- CentOS7 编译安装LNMP
(文章来自:http://www.cnblogs.com/i-it/p/3841840.html,请各位到这个网址去看原文的) LNMP(Linux-Nginx-Mysql-PHP),本文在CentO ...
- 树上点对统计poj1741(树的点分治)
给定一棵树,边上有权值,要统计有多少对点路径的权值和<=k 分治算法在树的路径中的应用 这个论文里面有分析. 任意两点的路径,要么过根结点,要么在子树中.如果在子树中,那么只要递归处理就行了. ...
- HibernateReview Day2–Hibernate体系结构
本文摘自 李刚 著 <Java EE企业应用实战> 现在我们知道了一个概念Hibernate Session,只有处于Session管理下的POJO才具有持久化操作能力.当应用程序对于处于 ...
- Java的wait(), notify()和notifyAll()使用心得(转)
本篇文章是对java的 wait(),notify(),notifyAll()进行了详细的分析介绍,需要的朋友参考下wait(),notify()和notifyAll()都是java.lang.Obj ...
- ASP.NET Core MVC Hello World
ASP.NET Core 现在ASP.NET Core还在不断成长.更新中,说不定到了明天又换了个模样,就如同一个小孩,从蹒跚学步,到奔向未来. 所以我们可以相应的去理解更新中所发生的变化,包容它.呵 ...
- 【原创】shadowebdict开发日记:基于linux的简明英汉字典(二)
全系列目录: [原创]shadowebdict开发日记:基于linux的简明英汉字典(一) [原创]shadowebdict开发日记:基于linux的简明英汉字典(二) [原创]shadowebdic ...
- POJ 3684 Priest John's Busiest Day 2-SAT+输出路径
强连通算法推断是否满足2-sat,然后反向建图,拓扑排序+染色. 一种选择是从 起点開始,还有一种是终点-持续时间那个点 開始. 若2个婚礼的某2种时间线段相交,则有矛盾,建边. easy出错的地方就 ...
- 【从翻译mos文章】Weblogic AdminServer 启动fail,报错"unable to get file lock, will retry"
Weblogic AdminServer 启动fail,报错"unable to get file lock, will retry" 参考原始: Weblogic AdminSe ...
