MSSQL:删除重复项的过程

时间:2016-04-15 12:07:26

标签: sql sql-server tsql stored-procedures distinct

考虑没有任何主键或外键的表。 我想编写一个过程,它将删除给定表名的所有重复行。

如果所有字段都相同,则该行应被视为与其他行重复。

如果可能的话,你能建议我吗?我尝试的一件事是按每个领域分组,但这种方法并不普遍。

3 个答案:

答案 0 :(得分:5)

您可以使用Dynamic-SQL实现它

快速支持的解决方案(很大的改进空间):

CREATE TABLE tab1(a INT, b INT);
INSERT INTO tab1(a,b) VALUES (1,1),(1,1),(1,1),(2,3);
GO

步骤:

CREATE PROCEDURE dbo.remove_duplicates
    @tab_name SYSNAME
    ,@debug BIT = 0
AS
BEGIN
    SET NOCOUNT ON;
    -- TODO: validation if table does not exist, raise error
    -- TODO: Add @schema parameter
    -- TODO: Wrap with BEGIN TRY, omit calculated columns, CAST `TEXT/IMAGE/BINARY`....

    DECLARE @sql NVARCHAR(MAX) = 
       'WITH cte AS
        (
            SELECT *, rn = ROW_NUMBER() OVER(PARTITION BY <cols> ORDER BY (SELECT 1))
            FROM <tab_placeholder>
        )
        DELETE FROM cte
        WHERE rn <> 1;';

    DECLARE @cols NVARCHAR(MAX) = STUFF((SELECT ',' +  column_name
                                         FROM INFORMATION_SCHEMA.COLUMNS
                                         WHERE TABLE_NAME = @tab_name
                                           AND TABLE_SCHEMA = 'dbo'
                                         FOR XML PATH('')), 1, 1, '');    

    SET @sql = REPLACE(@sql, '<tab_placeholder>', QUOTENAME(@tab_name));
    SET @sql = REPLACE(@sql, '<cols>', @cols);

    IF @debug = 1 SELECT @sql;

    EXEC dbo.sp_executesql @sql;    

END
GO

执行:

EXEC [dbo].[remove_duplicates] @tab_name = 'tab1', @debug = 1;
SELECT * FROM tab1;

LiveDemo

答案 1 :(得分:0)

这将从表中删除重复项。您的分区必须包含您希望分组的字段,以确定重复的内容。在你的情况下,所有这些。

IF OBJECT_ID('tempdb..#TABLE') IS NOT NULL DROP TABLE #TABLE

CREATE TABLE #TABLE ( SOMEINT INT,SOMEVALUE VARCHAR(255) )
INSERT INTO #TABLE ( SOMEINT, SOMEVALUE )
VALUES (1,'VALUE1')
,(1,'VALUE2')
,(1,'VALUE2')
,(1,'VALUE3')
,(1,'VALUE4')
,(1,'VALUE4')
,(1,'VALUE4')
,(1,'VALUE4')
,(1,'VALUE5')
,(1,'VALUE6')
,(1,'VALUE6')
,(1,'VALUE6')
,(1,'VALUE7')
,(1,'VALUE8')
,(1,'VALUE8')
,(1,'VALUE9')
,(1,'VALUE10')

;WITH dedup
AS
( 
SELECT *, ROW_NUMBER() OVER (PARTITION BY SOMEINT,SOMEVALUE ORDER BY SOMEINT ASC) AS SEQUENCE
FROM #TABLE
)
DELETE
FROM dedup
WHERE SEQUENCE > 1
GO

SELECT * FROM #TABLE

答案 2 :(得分:0)

有多种方式

首先,

创建临时表,并将不同的数据复制到该临时表。删除或截断实际表中的数据。并将临时表复制到您的实际表中。删除临时表

SELECT DISTINCT * INTO #table1 from TABLE1
DELETE FROM TABLE1
INSERT INTO TABLE1
SELECT * FROM #table1
DROP TABLE #table1

其次,

向表中添加一列,使用ROW_NUMBER PARTITION更新该列,然后删除COLUMN&lt;&gt;中的行1。删除新创建的列。