Wählen Sie eine Anweisung aus, um Duplikate in bestimmten Feldern zu finden


415

Können Sie mir mit SQL-Anweisungen helfen, Duplikate in mehreren Feldern zu finden?

Zum Beispiel im Pseudocode:

select count(field1,field2,field3) 
from table 
where the combination of field1, field2, field3 occurs multiple times

und aus der obigen Aussage möchte ich bei mehreren Vorkommen jeden Datensatz außer dem ersten auswählen .


3
Ihr Pseudocode ist mehrdeutig und Sie definieren keine Reihenfolge, nach der Sie die erste nicht möchten. Ich schlage vor, Sie geben einige Beispieldaten.
Unvernunft

Antworten:


840

Um die Liste der Felder abzurufen, für die mehrere Datensätze vorhanden sind, können Sie Folgendes verwenden:

select field1,field2,field3, count(*)
  from table_name
  group by field1,field2,field3
  having count(*) > 1

Überprüfen Sie diesen Link, um weitere Informationen zum Löschen der Zeilen zu erhalten.

http://support.microsoft.com/kb/139444

Bearbeiten: Wie die anderen Benutzer erwähnt haben, sollte es ein Kriterium für die Entscheidung geben, wie Sie "erste Zeilen" definieren, bevor Sie den Ansatz im obigen Link verwenden. Basierend darauf müssen Sie bei Bedarf eine order by-Klausel und eine Unterabfrage verwenden. Wenn Sie einige Beispieldaten veröffentlichen können, wäre dies wirklich hilfreich.


42

Sie erwähnen "den ersten", also gehe ich davon aus, dass Sie eine Art Bestellung für Ihre Daten haben. Nehmen wir an, dass Ihre Daten nach Feldern sortiert sind ID.

Diese SQL sollte Ihnen die doppelten Einträge mit Ausnahme des ersten erhalten. Grundsätzlich werden alle Zeilen ausgewählt, für die eine andere Zeile mit (a) denselben Feldern und (b) einer niedrigeren ID vorhanden ist. Die Leistung wird nicht großartig sein, aber sie könnte Ihr Problem lösen.

SELECT A.ID, A.field1, A.field2, A.field3
  FROM myTable A
 WHERE EXISTS (SELECT B.ID
                 FROM myTable B
                WHERE B.field1 = A.field1
                  AND B.field2 = A.field2
                  AND B.field3 = A.field3
                  AND B.ID < A.ID)

17

Dies ist eine unterhaltsame Lösung mit SQL Server 2005, die mir gefällt. Ich gehe davon aus, dass mit "für jeden Datensatz außer dem ersten" eine weitere "id" -Spalte gemeint ist, anhand derer wir identifizieren können, welche Zeile "erste" ist.

SELECT id
    , field1
    , field2
    , field3
FROM
(
    SELECT id
        , field1
        , field2
        , field3
        , RANK() OVER (PARTITION BY field1, field2, field3 ORDER BY id ASC) AS [rank]
    FROM table_name
) a
WHERE [rank] > 1

Ich habe gerade das SQL Server 2008-Tag bemerkt. Ich bin froh, dass mein Vorschlag noch gültig ist.
Nick Vaccaro

1
Ausgezeichnete Lösung, da es auch die Zeilen zurückgibt, die aus der fraglichen Tabelle gelöscht werden müssen
Realto619

1
Es ist hilfreich, sich die Feldliste PARTITION BY als eine Liste der PK-Felder
vorzustellen

6

So zeigen Sie doppelte Werte an:

with MYCTE  as (
    select row_number() over ( partition by name  order by name) rown, *
    from tmptest  
    ) 
select * from MYCTE where rown <=1

3

Wenn Sie SQL Server 2005 oder höher verwenden (und die Tags für Ihre Frage geben SQL Server 2008 an), können Sie mithilfe von Ranking-Funktionen die doppelten Datensätze nach dem ersten zurückgeben, wenn die Verwendung von Joins aus irgendeinem Grund weniger wünschenswert oder unpraktisch ist. Das folgende Beispiel zeigt dies in Aktion, wo es auch mit Nullwerten in den untersuchten Spalten funktioniert.

create table Table1 (
 Field1 int,
 Field2 int,
 Field3 int,
 Field4 int 
)

insert  Table1 
values    (1,1,1,1)
        , (1,1,1,2)
        , (1,1,1,3)
        , (2,2,2,1)
        , (3,3,3,1)
        , (3,3,3,2)
        , (null, null, 2, 1)
        , (null, null, 2, 3)

select    *
from     (select      Field1
                    , Field2
                    , Field3
                    , Field4
                    , row_number() over (partition by   Field1
                                                      , Field2
                                                      , Field3
                                         order by       Field4) as occurrence
          from      Table1) x
where     occurrence > 1

Beachten Sie nach dem Ausführen dieses Beispiels, dass der erste Datensatz aus jeder "Gruppe" ausgeschlossen ist und dass Datensätze mit Nullwerten ordnungsgemäß behandelt werden.

Wenn Sie keine Spalte zum Ordnen der Datensätze innerhalb einer Gruppe zur Verfügung haben, können Sie die Spalten nach Partition als Spalten nach Reihenfolge verwenden.


1
CREATE TABLE #tmp
(
    sizeId Varchar(MAX)
)

INSERT  #tmp 
    VALUES ('44'),
        ('44,45,46'),
        ('44,45,46'),
        ('44,45,46'),
        ('44,45,46'),
        ('44,45,46'),
        ('44,45,46')


SELECT * FROM #tmp
DECLARE @SqlStr VARCHAR(MAX)

SELECT @SqlStr = STUFF((SELECT ',' + sizeId
              FROM #tmp
              ORDER BY sizeId
              FOR XML PATH('')), 1, 1, '') 


SELECT TOP 1 * FROM (
select items, count(*)AS Occurrence
  FROM dbo.Split(@SqlStr,',')
  group by items
  having count(*) > 1
  )K
  ORDER BY K.Occurrence DESC    

0

Versuchen Sie diese Abfrage, um die Anzahl der einzelnen SELECT-Anweisungen einzeln zu bestimmen:

select field1,count(field1) as field1Count,field2,count(field2) as field2Counts,field3, count(field3) as field3Counts
from table_name
group by field1,field2,field3
having count(*) > 1
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.