it-swarm.com.de

Wie lösche ich doppelte Zeilen in SQL Server?

Wie kann ichdelete duplicate rowswo kein unique row id existiert?

Mein Tisch ist

col1  col2 col3 col4 col5 col6 col7
john  1    1    1    1    1    1 
john  1    1    1    1    1    1
sally 2    2    2    2    2    2
sally 2    2    2    2    2    2

Ich möchte nach der doppelten Entfernung mit den folgenden Informationen stehen:

john  1    1    1    1    1    1
sally 2    2    2    2    2    2

Ich habe ein paar Abfragen ausprobiert, aber ich denke, sie hängen von einer Reihen-ID ab, da ich nicht das gewünschte Ergebnis bekomme. Zum Beispiel:

DELETE FROM table WHERE col1 IN (
    SELECT id FROM table GROUP BY id HAVING ( COUNT(col1) > 1 )
)
297
Fearghal

Ich mag CTEs und ROW_NUMBER, da wir durch die Kombination der beiden Zeilen sehen können, welche Zeilen gelöscht (oder aktualisiert) werden. Ändern Sie daher einfach den DELETE FROM CTE... in SELECT * FROM CTE:

WITH CTE AS(
   SELECT [col1], [col2], [col3], [col4], [col5], [col6], [col7],
       RN = ROW_NUMBER()OVER(PARTITION BY col1 ORDER BY col1)
   FROM dbo.Table1
)
DELETE FROM CTE WHERE RN > 1

DEMO (Das Ergebnis ist anders. Ich gehe davon aus, dass es auf einen Tippfehler von Ihnen zurückzuführen ist.)

COL1    COL2    COL3    COL4    COL5    COL6    COL7
john    1        1       1       1       1       1
sally   2        2       2       2       2       2

In diesem Beispiel werden Duplikate aufgrund des col1 durch eine einzelne Spalte PARTITION BY col1 ermittelt. Wenn Sie mehrere Spalten einfügen möchten, fügen Sie diese einfach zum PARTITION BY hinzu:

ROW_NUMBER()OVER(PARTITION BY Col1, Col2, ... ORDER BY OrderColumn)
688
Tim Schmelter

Ich würde CTE für das Löschen von doppelten Zeilen aus SQL Server-Tabelle bevorzugen

es wird dringend empfohlen, diesem Artikel zu folgen: http://codaffection.com/sql-server-article/delete-duplicate-rows-in-sql-server/

durch das Original halten

WITH CTE AS
(
SELECT *,ROW_NUMBER() OVER (PARTITION BY col1,col2,col3 ORDER BY col1,col2,col3) AS RN
FROM MyTable
)

DELETE FROM CTE WHERE RN<>1

ohne original zu halten

WITH CTE AS
(SELECT *,R=RANK() OVER (ORDER BY col1,col2,col3)
FROM MyTable)
 
DELETE CTE
WHERE R IN (SELECT R FROM CTE GROUP BY R HAVING COUNT(*)>1)
114
Shamseer K

Ohne CTE und ROW_NUMBER() können Sie die Datensätze einfach löschen, indem Sie group by mit MAX verwenden. Die Funktion ist hier und ein Beispiel

DELETE
FROM MyDuplicateTable
WHERE ID NOT IN
(
SELECT MAX(ID)
FROM MyDuplicateTable
GROUP BY DuplicateColumn1, DuplicateColumn2, DuplicateColumn3)
32
Aamir
DELETE from search
where id not in (
   select min(id) from search
   group by url
   having count(*)=1

   union

   SELECT min(id) FROM search
   group by url
   having count(*) > 1
)
13
Shoja Hamid

Microsoft hat eine sehr gute Anleitung zum Entfernen von Duplikaten. Auschecken http://support.Microsoft.com/kb/139444

Kurz gesagt, ist dies der einfachste Weg, Duplikate zu löschen, wenn Sie nur wenige Zeilen zum Löschen haben:

SET rowcount 1;
DELETE FROM t1 WHERE myprimarykey=1;

myprimarykey ist der Bezeichner für die Zeile.

Ich habe rowcount auf 1 gesetzt, da ich nur zwei Zeilen hatte, die dupliziert wurden. Wenn ich 3 Zeilen dupliziert hätte, hätte ich rowcount auf 2 gesetzt, so dass die ersten beiden gelöscht werden und nur eine in Tabelle t1 bleibt.

Ich hoffe es hilft jedem

6
oabarca

Bitte beachten Sie auch die unten stehende Löschmethode.

Declare @table table
(col1 varchar(10),col2 int,col3 int, col4 int, col5 int, col6 int, col7 int)
Insert into @table values 
('john',1,1,1,1,1,1),
('john',1,1,1,1,1,1),
('sally',2,2,2,2,2,2),
('sally',2,2,2,2,2,2)

Eine Beispieltabelle mit dem Namen @table wurde erstellt und mit den angegebenen Daten geladen.

 enter image description here

Delete  aliasName from (
Select  *,
        ROW_NUMBER() over (Partition by col1,col2,col3,col4,col5,col6,col7 order by col1) as rowNumber
From    @table) aliasName 
Where   rowNumber > 1

Select * from @table

 enter image description here

Hinweis: Wenn Sie alle Spalten im Partition by-Teil angeben, hat order by keine große Bedeutung.

Ich weiß, die Frage wurde vor drei Jahren gestellt, und meine Antwort ist eine andere Version dessen, was Tim gepostet hat.

5
Jithin Shaji

Nachdem Sie die oben vorgeschlagene Lösung ausprobiert haben, funktioniert dies für kleine mittlere Tabellen. Ich kann diese Lösung für sehr große Tabellen vorschlagen. da läuft es in iterationen.

  1. Alle Abhängigkeitsansichten von LargeSourceTable löschen
  2. sie können die Abhängigkeiten mit SQL Management Studio finden, indem Sie mit der rechten Maustaste auf die Tabelle klicken und auf "Abhängigkeiten anzeigen" klicken.
  3. Benennen Sie die Tabelle um:
  4. sp_rename 'LargeSourceTable', 'LargeSourceTable_Temp'; GO
  5. Erstellen Sie das LargeSourceTable erneut, aber fügen Sie jetzt einen Primärschlüssel mit allen Spalten hinzu, die die Duplikationen definieren. Add WITH (IGNORE_DUP_KEY = ON)
  6. Zum Beispiel:

    CREATE TABLE [dbo].[LargeSourceTable] ( ID int IDENTITY(1,1), [CreateDate] DATETIME CONSTRAINT [DF_LargeSourceTable_CreateDate] DEFAULT (getdate()) NOT NULL, [Column1] CHAR (36) NOT NULL, [Column2] NVARCHAR (100) NOT NULL, [Column3] CHAR (36) NOT NULL, PRIMARY KEY (Column1, Column2) WITH (IGNORE_DUP_KEY = ON) ); GO

  7. Erstellen Sie erneut die Ansichten, die Sie an erster Stelle für die neu erstellte Tabelle abgelegt haben

  8. Führen Sie nun das folgende SQL-Skript aus. Die Ergebnisse werden in 1.000.000 Zeilen pro Seite angezeigt. Sie können die Zeilennummer pro Seite ändern, um die Ergebnisse häufiger anzuzeigen.

  9. Beachten Sie, dass ich IDENTITY_INSERT Ein- und ausschalte, da eine der Spalten eine automatische inkrementelle ID enthält, die ich auch kopiere

SET IDENTITY_INSERT LargeSourceTable ON DECLARE @PageNumber AS INT, @RowspPage AS INT DECLARE @TotalRows AS INT declare @dt varchar(19) SET @PageNumber = 0 SET @RowspPage = 1000000select @TotalRows = count (*) from LargeSourceTable_TEMP

While ((@PageNumber - 1) * @RowspPage < @TotalRows )
Begin
    begin transaction tran_inner
        ; with cte as
        (
            SELECT * FROM LargeSourceTable_TEMP ORDER BY ID
            OFFSET ((@PageNumber) * @RowspPage) ROWS
            FETCH NEXT @RowspPage ROWS ONLY
        )

        INSERT INTO LargeSourceTable 
        (
             ID                     
            ,[CreateDate]       
            ,[Column1]   
            ,[Column2] 
            ,[Column3]       
        )       
        select 
             ID                     
            ,[CreateDate]       
            ,[Column1]   
            ,[Column2] 
            ,[Column3]       
        from cte

    commit transaction tran_inner

    PRINT 'Page: ' + convert(varchar(10), @PageNumber)
    PRINT 'Transfered: ' + convert(varchar(20), @PageNumber * @RowspPage)
    PRINT 'Of: ' + convert(varchar(20), @TotalRows)

    SELECT @dt = convert(varchar(19), getdate(), 121)
    RAISERROR('Inserted on: %s', 0, 1, @dt) WITH NOWAIT
    SET @PageNumber = @PageNumber + 1
End

SET IDENTITY_INSERT LargeSourceTable OFF

4
Moshe Taieb

Wenn Sie keine Referenzen wie Fremdschlüssel haben, können Sie dies tun. Ich mache viel, wenn ich Konzeptnachweise teste und die Testdaten dupliziert werden.

SELECT DISTINCT [col1], [col2], [col3], [col4], [col5], [col6], [col7]

INTO [neueTabelle]

;

Gehen Sie in den Objekt-Explorer und löschen Sie die alte Tabelle.

Benennen Sie die neue Tabelle mit dem Namen der alten Tabelle um.

3
Rhys
-- this query will keep only one instance of a duplicate record.
;WITH cte
     AS (SELECT ROW_NUMBER() OVER (PARTITION BY col1, col2, col3-- based on what? --can be multiple columns
                                       ORDER BY ( SELECT 0)) RN
         FROM   Mytable)



delete  FROM cte
WHERE  RN > 1
2
Hasan Shouman
     SELECT DISTINCT * FROM TABLE;

Dadurch werden alle doppelten Zeilen entfernt und Sie erhalten nur die eindeutigen Werte (Zeilen).

1
Prince_Prajwal

Wenn Sie der Tabelle vorübergehend eine Spalte hinzufügen können, war diese Lösung für mich eine Lösung:

ALTER TABLE dbo.DUPPEDTABLE ADD RowID INT NOT NULL IDENTITY(1,1)

Führen Sie dann ein LÖSCHEN mit einer Kombination aus MIN und GROUP BY aus

DELETE b
FROM dbo.DUPPEDTABLE b
WHERE b.RowID NOT IN (
                     SELECT MIN(RowID) AS RowID
                     FROM dbo.DUPPEDTABLE a WITH (NOLOCK)
                     GROUP BY a.ITEM_NUMBER,
                              a.CHARACTERISTIC,
                              a.INTVALUE,
                              a.FLOATVALUE,
                              a.STRINGVALUE
                 );

Stellen Sie sicher, dass das DELETE ordnungsgemäß ausgeführt wurde:

SELECT a.ITEM_NUMBER,
    a.CHARACTERISTIC,
    a.INTVALUE,
    a.FLOATVALUE,
    a.STRINGVALUE, COUNT(*)--MIN(RowID) AS RowID
FROM dbo.DUPPEDTABLE a WITH (NOLOCK)
GROUP BY a.ITEM_NUMBER,
    a.CHARACTERISTIC,
    a.INTVALUE,
    a.FLOATVALUE,
    a.STRINGVALUE
ORDER BY COUNT(*) DESC 

Das Ergebnis sollte keine Zeilen mit einer höheren Anzahl als 1 enthalten. Entfernen Sie schließlich die Rowid-Spalte:

ALTER TABLE dbo.DUPPEDTABLE DROP COLUMN RowID;
1
j.hull

In Bezug auf https://support.Microsoft.com/de-de/help/139444/how-to-remove-duplicate-rows-from-a-table-in-sql-server

Die Idee, ein Duplikat zu entfernen, beinhaltet 

  • a) Schutz der Zeilen, die nicht doppelt vorhanden sind
  • b) Behalten Sie eine der vielen Zeilen, die sich als Duplikat qualifizieren.

Schritt für Schritt

  • 1) Identifizieren Sie zunächst die Zeilen, die der Definition von Duplikat Entsprechen, und fügen Sie sie in die temporäre Tabelle ein, beispielsweise #tableAll.
  • 2) Wählen Sie nicht doppelte (einzeilige) oder unterschiedliche Zeilen in der temporären Tabelle aus Sagen Sie #tableUnique.
  • 3) Löschen Sie aus der Quelltabelle, indem Sie #tableAll hinzufügen, um die -Duplikate zu löschen.
  • 4) Fügen Sie alle Zeilen aus #tableUnique in die Quelltabelle ein.
  • 5) Lassen Sie #tableAll und #tableUnique fallen
1
rajibdotnet
with myCTE
as

(
select productName,ROW_NUMBER() over(PARTITION BY productName order by slno) as Duplicate from productDetails
)
Delete from myCTE where Duplicate>1
1
Debendra Dash
DECLARE @TB TABLE(NAME VARCHAR(100));
INSERT INTO @TB VALUES ('Red'),('Red'),('Green'),('Blue'),('White'),('White')
--**Delete by Rank**
;WITH CTE AS(SELECT NAME,DENSE_RANK() OVER (PARTITION BY NAME ORDER BY NEWID()) ID FROM @TB)
DELETE FROM CTE WHERE ID>1
SELECT NAME FROM @TB;
--**Delete by Row Number** 
;WITH CTE AS(SELECT NAME,ROW_NUMBER() OVER (PARTITION BY NAME ORDER BY NAME) ID FROM @TB)
DELETE FROM CTE WHERE ID>1;
SELECT NAME FROM @TB;
0
Surinder Singh

Sie müssen nach den doppelten Datensätzen nach den Feldern gruppieren, dann einen der Datensätze halten und den Rest löschen. __ Beispiel:

DELETE prg.Person WHERE Id IN ( SELECT dublicateRow.Id FROM ( select MIN(Id) MinId, NationalCode from prg.Person group by NationalCode having count(NationalCode ) > 1 ) GroupSelect JOIN prg.Person dublicateRow ON dublicateRow.NationalCode = GroupSelect.NationalCode WHERE dublicateRow.Id <> GroupSelect.MinId)

0
Hadi Salehy

Das Löschen von Duplikaten aus einer riesigen Tabelle (mehrere Millionen Datensätze) kann lange dauern. Ich schlage vor, dass Sie eine Masseneinfügung in eine temporäre Tabelle der ausgewählten Zeilen vornehmen, anstatt sie zu löschen.

--REWRITING YOUR CODE(TAKE NOTE OF THE 3RD LINE) WITH CTE AS(SELECT NAME,ROW_NUMBER() 
OVER (PARTITION BY NAME ORDER BY NAME) ID FROM @TB) SELECT * INTO #unique_records FROM 
CTE WHERE ID =1;
0
Emmanuel Bull

Oh wow, ich fühle mich so dumm von all diesen Antworten. Sie sind wie die Antworten von Experten mit allen CTE- und Temp-Tabellen und so weiter.

Und alles, was ich getan habe, um es zum Laufen zu bringen, war einfach die ID-Spalte mit MAX zu aggregieren.

DELETE FROM table WHERE col1 IN (
    SELECT MAX(id) FROM table GROUP BY id HAVING ( COUNT(col1) > 1 )
)

ANMERKUNG: Möglicherweise müssen Sie es mehrmals ausführen, um doppelte Zeilen zu entfernen, da dadurch jeweils nur ein Satz doppelter Zeilen gelöscht wird.

0
messed-up

Dies kann in SQL Server auf verschiedene Arten erfolgen. Am einfachsten ist dies: Fügen Sie die einzelnen Zeilen aus der doppelten Zeilentabelle in die neue temporäre Tabelle ein. Löschen Sie dann alle Daten aus der doppelten Zeilentabelle und fügen Sie dann alle Daten aus der temporären Tabelle ein, die keine Duplikate enthält, wie unten gezeigt.

select distinct * into #tmp From table
   delete from table
   insert into table
   select * from #tmp drop table #tmp

   select * from table

Doppelte Zeilen mit Common Table Expression (CTE) löschen

With CTE_Duplicates as

(wähle id, name, row_number () über (partition by id, name order by id, name) rownumber from table) lösche aus CTE_Duplicates wo rownumber! = 1

Eine andere Möglichkeit, doppelte Zeilen zu entfernen, ohne in einem Schritt Informationen zu verlieren, ist wie folgt:

delete from dublicated_table t1 (nolock)
join (
    select t2.dublicated_field
    , min(len(t2.field_kept)) as min_field_kept
    from dublicated_table t2 (nolock)
    group by t2.dublicated_field having COUNT(*)>1
) t3 
on t1.dublicated_field=t3.dublicated_field 
    and len(t1.field_kept)=t3.min_field_kept
0

Versuchen zu benutzen: 

SELECT linkorder
    ,Row_Number() OVER (
        PARTITION BY linkorder ORDER BY linkorder DESC
        ) AS RowNum
FROM u_links

 enter image description here

0
Fezal halai