2016-04-15 9 views
-2

Betrachten Sie die Tabelle, die keine primären oder fremden Schlüssel hat. Ich möchte eine Prozedur schreiben, die alle doppelten Zeilen mit dem Tabellennamen entfernt.MSSQL: Prozedur zum Entfernen von Duplikaten

Die Zeile sollte als Duplikat eines anderen betrachtet werden, wenn alle Felder identisch sind.

Können Sie mir vorschlagen, wenn dies möglich ist. Eine Sache, die ich versuchte, ist, nach jedem Feld zu gruppieren, aber dieser Ansatz ist nicht universell.

+0

Mögliches Duplikat von [Doppelte Datensätze aus einer SQL-Tabelle ohne Primärschlüssel löschen] (http://stackoverflow.com/questions/985384/delete-duplicate-records-from-a-sql-table-withouta- Primärschlüssel) –

Antwort

4

könnten Sie erreichen es mit Dynamic-SQL

Schnell backed-Lösung (großer Raum für Verbesserungen):

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

Vorgehen:

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 

Ausführung:

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

LiveDemo

+1

Danke, eigentlich habe ich nach einem allgemeinen Ansatz gesucht, mich nicht auf Tabellenspalten zu verlassen. Aber am Ende bekommst du sie auch und dann Teil. Aber das löst mein so akzeptiertes Problem. – seeker

+0

Der Fall, dass Sie sich auf Tabellenspalten (auf die eine oder andere Weise) verlassen müssen :) Es gibt nicht so etwas wie 'SELECT * FROM Tab GROUP BY *' :) – lad2025

0

Dies wird Duplikate aus einer Tabelle entfernen. Ihre Partition nach muss die Felder enthalten, nach denen Sie gruppieren möchten, um festzustellen, um was für ein Duplikat es sich handelt. In Ihrem Fall alle.

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 
0

Es gibt eine Reihe von Möglichkeiten,

Zuerst

eine temporäre Tabelle erstellen, und kopieren Sie verschiedene Daten auf diese temporäre Tabelle. Löschen oder kürzen Sie die Daten aus Ihrer aktuellen Tabelle. Und kopieren Sie die temporäre Tabelle in Ihre aktuelle Tabelle. Löschen Sie die temporäre Tabelle

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

oder

Zweitens

In einer Spalte in der Tabelle aktualisieren, dass die Spalte ROW_NUMBER PARTITION verwenden, dann entfernen Sie die Zeilen, in denen COLUMN <> 1. Löschen Sie die neu erstellte Spalte.