Duplikate aus einer Tabelle löschen

//Duplikate aus einer Tabelle löschen

Duplikate aus einer Tabelle löschen

Ich möchte hier mal einen kleinen Beitrag zum Thema “Duplikate aus einer Tabelle löschen” schreiben.
Das ist ein weit verbreitetes Thema und es gibt dafür viele verschiedenen Möglichkeiten das zu tun.


Das einfachste ist wenn die Tabelle einen Primärschlüssel beinhaltet.

CREATE TABLE [dbo].[TableDuplicatesA] ([ID]  [int]           IDENTITY(1,1) NOT NULL,
                                       [Key] [varchar](50)                 NOT NULL
CONSTRAINT [pk_dbo_TableDuplicatesA] PRIMARY KEY CLUSTERED 
([ID] ASC)
WITH (PAD_INDEX               = OFF,
      STATISTICS_NORECOMPUTE  = OFF,
	  IGNORE_DUP_KEY          = OFF,
	  ALLOW_ROW_LOCKS         = ON,
	  ALLOW_PAGE_LOCKS        = ON) ON [PRIMARY]) ON [PRIMARY]
INSERT INTO [dbo].[TableDuplicatesA] ([Key]) VALUES ('KeyA')
INSERT INTO [dbo].[TableDuplicatesA] ([Key]) VALUES ('KeyB')
INSERT INTO [dbo].[TableDuplicatesA] ([Key]) VALUES ('KeyB')
INSERT INTO [dbo].[TableDuplicatesA] ([Key]) VALUES ('KeyC')
INSERT INTO [dbo].[TableDuplicatesA] ([Key]) VALUES ('KeyD')
INSERT INTO [dbo].[TableDuplicatesA] ([Key]) VALUES ('KeyD')

Der entsprechende DELETE ist einfach und übersichtlich:

DELETE FROM [dbo].[TableDuplicatesA]
WHERE [ID] IN (SELECT max([ID])
               FROM [dbo].[TableDuplicatesA]
               GROUP BY [Key]
               HAVING count([Key]) > 1)


Kniffliger wird es wenn es keinen Primärschlüssel gibt.

CREATE TABLE [dbo].[TableDuplicatesB] ([Key] [varchar](50) NOT NULL) ON [PRIMARY]
INSERT INTO [dbo].[TableDuplicatesB] ([Key]) VALUES ('KeyA')
INSERT INTO [dbo].[TableDuplicatesB] ([Key]) VALUES ('KeyB')
INSERT INTO [dbo].[TableDuplicatesB] ([Key]) VALUES ('KeyB')
INSERT INTO [dbo].[TableDuplicatesB] ([Key]) VALUES ('KeyC')
INSERT INTO [dbo].[TableDuplicatesB] ([Key]) VALUES ('KeyD')
INSERT INTO [dbo].[TableDuplicatesB] ([Key]) VALUES ('KeyD')

Hier ein paar Beispiele:

Die wohl schlechteste Variante ist diese hier:

SELECT DISTINCT [Key]
INTO #temp
FROM [dbo].[TableDuplicatesB]
TRUNCATE TABLE [dbo].[TableDuplicatesB]
INSERT INTO [dbo].[TableDuplicatesB]
SELECT * FROM #temp
SELECT * FROM [dbo].[TableDuplicatesA]
DROP TABLE #temp

Besser und eleganter sind die nachfolgenden drei Beispiele:

DELETE t1
FROM (SELECT *, 
       ROW_NUMBER() OVER (PARTITION BY [Key] ORDER BY [Key] DESC) [RowID] 
FROM [dbo].[TableDuplicatesB]) t1
WHERE [RowID] > 1


WITH CTE_Duplicates
AS (SELECT ROW_NUMBER() OVER (PARTITION BY [Key] ORDER BY (SELECT 0)) [RowNumber]
    FROM [dbo].[TableDuplicatesB])
DELETE FROM CTE_Duplicates
WHERE [RowNumber] > 1


DELETE t1
FROM (SELECT ROW_NUMBER() OVER (ORDER BY [Key]) AS [RowID],
             [Key]
      FROM [dbo].[TableDuplicatesB]) t1,
	 (SELECT ROW_NUMBER() OVER (ORDER BY [Key]) AS [RowID],
	         [Key]
      FROM [dbo].[TableDuplicatesB]) t2
WHERE t1.[Key]   = t2.[Key]
AND   t1.[RowID] > t2.[RowID]

Anhand der Execution Plans könnt Ihr Euch selber ein Bild machen und entscheiden welche Query für Euch passt.

Von |2015-06-20T20:38:12+00:00Juni 15th, 2015|SQL Blog|0 Kommentare

About the Author:

Frank Uray

Hinterlassen Sie einen Kommentar