T-SQL技术收集——删除重复数据

简介: 原文: T-SQL技术收集——删除重复数据          在工作和面试中,经常出现如何查询或者删除重复数据的问题,如果有主键,那还好办一点,如果没有主键,那就有点麻烦。
原文: 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

--结果仅返回3

         结果如下:


--使用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

--结果返回3

 

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 MyT

    WHERE [sid] IN

    (

        SELECT [sid] FROM MyT

        GROUP BY [sid],sname

        HAVING COUNT(1)>1

    )

    IF @@ROWCOUNT=0

    BREAK

END

SET ROWCOUNT 0

 

--可以发现,重复的数据已经删除

SELECT * FROM MyT


第二种方法:

使用DELETE TOP(N)方法,先把刚才插入测试数据的脚本再执行,可以多执行几次。DELETE TOP(1)可以用来替代SET ROWCOUNT 1:

WHILE 1=1

BEGIN

    DELETE TOP(1) FROM MyT

    WHERE [sid] IN

    (

        SELECT [sid] FROM MyT

        GROUP BY [sid],sname

        HAVING COUNT(1)>1

    )

    IF @@ROWCOUNT=0

    BREAK

END

 

结果和上面的一样。

 

扩充:保留最近的一行数据:

有时候不仅仅要去掉重复数据,也要保证剩下的是最新的数据(日期最大),此时可以借助索引,使用索引排序,然后把日期最小的那些删掉,只保留日期最大的那一笔。

--建立复合索引,利用索引将数据以编号和日期升序排序

CREATE INDEX IDX_DT ON MyT([sid],sdt ASC)

GO

--修改删除语句,搭配with index查询提示

WHILE 1=1

BEGIN

    DELETE TOP(1) FROM MyT

    WHERE [sid] IN

    (

        SELECT [sid] FROM MyT WITH (INDEX(idx_dt))

        GROUP BY [sid],sname

        HAVING COUNT(1) >1

    )

    IF @@ROWCOUNT=0

    BREAK

END

 

查询结果:

SELECT * FROM MyT

 

注意:

为了向后兼容,括号在 SELECT 语句中是可选的。

我们建议您始终对 SELECT 语句中的 TOP 使用括号,这样,就可以与在 INSERT、UPDATE、MERGE 和 DELETE 语句中需要使用括号保持一致(在这种情况下括号是必需的)。

(出自SQL SERVER 2012联机丛书)

 

目录
相关文章
|
1月前
|
SQL 存储 算法
比 SQL 快出数量级的大数据计算技术
SQL 是大数据计算中最常用的工具,但在实际应用中,SQL 经常跑得很慢,浪费大量硬件资源。例如,某银行的反洗钱计算在 11 节点的 Vertica 集群上跑了 1.5 小时,而用 SPL 重写后,单机只需 26 秒。类似地,电商漏斗运算和时空碰撞任务在使用 SPL 后,性能也大幅提升。这是因为 SQL 无法写出低复杂度的算法,而 SPL 提供了更强大的数据类型和基础运算,能够实现高效计算。
|
1月前
|
SQL 存储 缓存
SQL Server 数据太多如何优化
11种优化方案供你参考,优化 SQL Server 数据库性能得从多个方面着手,包括硬件配置、数据库结构、查询优化、索引管理、分区分表、并行处理等。通过合理的索引、查询优化、数据分区等技术,可以在数据量增大时保持较好的性能。同时,定期进行数据库维护和清理,保证数据库高效运行。
|
2月前
|
SQL 移动开发 Oracle
SQL语句实现查询连续六天数据的方法与技巧
在数据库查询中,有时需要筛选出符合特定时间连续性条件的数据记录
|
2月前
|
SQL 存储 关系型数据库
添加数据到数据库的SQL语句详解与实践技巧
在数据库管理中,添加数据是一个基本操作,它涉及到向表中插入新的记录
|
2月前
|
SQL 数据挖掘 数据库
SQL查询每秒的数据:技巧、方法与性能优化
id="">SQL查询功能详解 SQL(Structured Query Language,结构化查询语言)是一种专门用于与数据库进行沟通和操作的语言
|
2月前
|
SQL 监控 数据处理
SQL数据库数据修改操作详解
数据库是现代信息系统的重要组成部分,其中SQL(StructuredQueryLanguage)是管理和处理数据库的重要工具之一。在日常的业务运营过程中,数据的准确性和及时性对企业来说至关重要,这就需要掌握如何在数据库中正确地进行数据修改操作。本文将详细介绍在SQL数据库中如何修改数据,帮助读者更好
411 4
|
2月前
|
SQL 安全 数据库
sql注入技术
sql注入技术
|
2月前
|
SQL 分布式计算 关系型数据库
Hadoop-24 Sqoop迁移 MySQL到Hive 与 Hive到MySQL SQL生成数据 HDFS集群 Sqoop import jdbc ETL MapReduce
Hadoop-24 Sqoop迁移 MySQL到Hive 与 Hive到MySQL SQL生成数据 HDFS集群 Sqoop import jdbc ETL MapReduce
104 0
|
2月前
|
SQL 分布式计算 关系型数据库
Hadoop-23 Sqoop 数据MySQL到HDFS(部分) SQL生成数据 HDFS集群 Sqoop import jdbc ETL MapReduce
Hadoop-23 Sqoop 数据MySQL到HDFS(部分) SQL生成数据 HDFS集群 Sqoop import jdbc ETL MapReduce
48 0
|
2月前
|
SQL 分布式计算 关系型数据库
Hadoop-22 Sqoop 数据MySQL到HDFS(全量) SQL生成数据 HDFS集群 Sqoop import jdbc ETL MapReduce
Hadoop-22 Sqoop 数据MySQL到HDFS(全量) SQL生成数据 HDFS集群 Sqoop import jdbc ETL MapReduce
57 0
下一篇
DataWorks