SQLite
 sql >> Datenbank >  >> RDS >> SQLite

11 Möglichkeiten, doppelte Zeilen zu finden, während der Primärschlüssel in SQLite ignoriert wird

Hier sind elf Optionen zum Zurückgeben doppelter Zeilen in SQLite, wenn diese Zeilen einen Primärschlüssel oder eine andere eindeutige Bezeichnerspalte haben (aber Sie den Primärschlüssel ignorieren möchten).

Das bedeutet, dass die doppelten Zeilen in allen Spalten genau die gleichen Werte aufweisen, mit Ausnahme ihrer Primärschlüssel-/eindeutigen ID-Spalte.

Beispieldaten

Wir verwenden die folgenden Daten für unsere Beispiele:

SELECT * FROM Dogs; 

Ergebnis:

HundId Vorname Nachname ----- --------- -------- 1 Bark Smith 2 Bark Smith 3 Woof Jones 4 Ruff Robinson5 Wag Johnson 6 Wag Johnson 7 Wag Johnson  

Die ersten beiden Zeilen sind Duplikate (mit Ausnahme der DogId Spalte, die der Primärschlüssel der Tabelle ist und einen eindeutigen Wert für alle Zeilen enthält). Die letzten drei Zeilen sind ebenfalls Duplikate (mit Ausnahme der DogId Spalte).

Die Primärschlüsselspalte stellt sicher, dass es keine doppelten Zeilen gibt, was sich in RDBMS bewährt hat, da Primärschlüssel dabei helfen, die Datenintegrität durchzusetzen. Da Primärschlüssel jedoch doppelte Zeilen verhindern, können sie unsere Fähigkeit beeinträchtigen, Duplikate zu finden.

In unserer obigen Tabelle ist die Primärschlüsselspalte eine aufsteigende Zahl, und ihr Wert hat keine Bedeutung und ist nicht signifikant. Wir müssen diese Zeile daher ignorieren, wenn wir Duplikate in den anderen Spalten finden wollen.

Möglichkeit 1

Wir können eine Abfrage mit dem GROUP BY ausführen -Klausel, um die Spalten nach ihren signifikanten Spalten zu gruppieren, verwenden Sie dann COUNT() Funktion, um die Anzahl identischer Zeilen zurückzugeben:

SELECT 
    FirstName, 
    LastName, 
    COUNT(*) AS Count
FROM Dogs
GROUP BY FirstName, LastName
ORDER BY Count DESC; 

Ergebnis:

Vorname Nachname Anzahl --------- -------- -----Wag Johnson 3 Bark Smith 2 Ruff Robinson 1 Woof Jones 1 

Hier haben wir die Primärschlüsselspalte ausgeschlossen, indem wir sie aus unserer Abfrage weggelassen haben. Wir haben es auch nach Anzahl in absteigender Reihenfolge sortiert, sodass die Duplikate zuerst angezeigt werden.

Das Ergebnis sagt uns, dass es drei Zeilen mit Wag Johnson und zwei Zeilen mit Bark Smith gibt. Dies sind Duplikate (oder Triplikate im Fall von Wag Johnson). Die anderen beiden Zeilen haben keine Duplikate.

Option 2

Wir können den HAVING verwenden -Klausel, um Nicht-Duplikate von der Ausgabe auszuschließen:

SELECT 
    FirstName, 
    LastName, 
    COUNT(*) AS Count
FROM Dogs
GROUP BY FirstName, LastName
HAVING COUNT(*) > 1
ORDER BY Count DESC; 

Ergebnis:

Vorname Nachname Anzahl --------- -------- -----Wag Johnson 3 Bark Smith 2 

Möglichkeit 3

Hier ist ein Beispiel für die Suche nach Duplikaten in verketteten Spalten. In diesem Fall verwenden wir den DISTINCT Schlüsselwort, um unterschiedliche Werte zu erhalten, und verwenden Sie dann COUNT() Funktion, um die Zählung zurückzugeben:

SELECT
    DISTINCT FirstName || ' ' || LastName AS DogName,
    COUNT(*) AS Count
FROM Dogs
GROUP BY FirstName || ' ' || LastName
ORDER BY Count DESC; 

Ergebnis:

DogName Count------------- -----Wag Johnson 3 Bark Smith 2 Woof Jones 1 Ruff Robinson 1 

Option 4

Standardmäßig hat jede Zeile in SQLite eine spezielle Spalte, die normalerweise als rowid bezeichnet wird , die diese Zeile innerhalb der Tabelle eindeutig identifiziert. Sofern es nicht ausdrücklich aus der Tabelle entfernt wurde, können Sie dies als eindeutige Kennung für jede Zeile verwenden.

Wir können daher die rowid verwenden in unserer Abfrage:

SELECT * FROM Dogs
WHERE EXISTS (
  SELECT 1 FROM Dogs d2 
  WHERE Dogs.FirstName = d2.FirstName
  AND Dogs.LastName = d2.LastName
  AND Dogs.rowid > d2.rowid
); 

Ergebnis:

HundId Vorname Nachname ----- --------- -------- 2 Bark Smith 6 Wag Johnson 7 Wag Johnson 

Wir könnten SELECT * ersetzen mit DELETE um eine Deduplizierungsoperation auf der Tabelle durchzuführen.

Beachten Sie, dass wir die DogId hätten verwenden können Spalte (unser Primärschlüssel) anstelle der rowid wenn wir wollten. Das heißt, die rowid kann nützlich sein, wenn Sie die Primärschlüsselspalte aus irgendeinem Grund nicht verwenden können oder wenn die Tabelle keinen Primärschlüssel hat.

Option 5

Hier ist eine weitere Abfrage, die die rowid verwendet :

SELECT * FROM Dogs
WHERE rowid > (
  SELECT MIN(rowid) FROM Dogs d2  
  WHERE Dogs.FirstName = d2.FirstName
  AND Dogs.LastName = d2.LastName
); 

Ergebnis:

HundId Vorname Nachname ----- --------- -------- 2 Bark Smith 6 Wag Johnson 7 Wag Johnson 

Wie im vorherigen Beispiel könnten wir den SELECT * ersetzen mit DELETE um die doppelten Zeilen zu löschen.

Option 6

Die beiden rowid Die obigen Optionen sind großartig, wenn Sie den Primärschlüssel in Ihrer Abfrage vollständig ignorieren müssen (oder wenn Sie überhaupt keine Primärschlüsselspalte haben). Wie bereits erwähnt, besteht jedoch immer noch die Möglichkeit, rowid zu ersetzen mit der Primärschlüsselspalte – in unserem Fall die DogId Spalte:

SELECT * FROM Dogs
WHERE EXISTS (
  SELECT 1 FROM Dogs d2 
  WHERE Dogs.FirstName = d2.FirstName
  AND Dogs.LastName = d2.LastName
  AND Dogs.DogId > d2.DogId
); 

Ergebnis:

HundId Vorname Nachname ----- --------- -------- 2 Bark Smith 6 Wag Johnson 7 Wag Johnson 

Option 7

Und hier ist die andere Abfrage mit der rowid durch die DogId ersetzt Spalte:

SELECT * FROM Dogs
WHERE DogId > (
  SELECT MIN(DogId) FROM Dogs d2  
  WHERE Dogs.FirstName = d2.FirstName
  AND Dogs.LastName = d2.LastName
); 

Ergebnis:

HundId Vorname Nachname ----- --------- -------- 2 Bark Smith 6 Wag Johnson 7 Wag Johnson 

Option 8

Eine andere Möglichkeit ist die Verwendung von ROW_NUMBER() Fensterfunktion:

SELECT 
    *,
    ROW_NUMBER() OVER ( 
        PARTITION BY FirstName, LastName 
        ORDER BY FirstName, LastName
        ) AS Row_Number
FROM Dogs; 

Ergebnis:

DogId FirstName LastName Row_Number----- --------- -------- ----------1 Bark Smith 1 2 Bark Smith 2 4 Ruff Robinson 1 5 Wag Johnson 1 6 Wag Johnson 2 7 Wag Johnson 3 3 Woof Jones 1 

Verwenden der PARTITION -Klausel führt dazu, dass eine neue Spalte hinzugefügt wird, mit einer Zeilennummer, die sich jedes Mal erhöht, wenn es ein Duplikat gibt, aber wieder zurückgesetzt wird, wenn es eine eindeutige Zeile gibt.

In diesem Fall gruppieren wir die Ergebnisse nicht, was bedeutet, dass wir jede doppelte Zeile sehen können, einschließlich ihrer eindeutigen ID-Spalte.

Option 9

Wir können das vorherige Beispiel auch als allgemeinen Tabellenausdruck in einer größeren Abfrage verwenden:

WITH cte AS 
    (
        SELECT 
            *,
            ROW_NUMBER() OVER ( 
                PARTITION BY FirstName, LastName 
                ORDER BY FirstName, LastName
                ) AS Row_Number
        FROM Dogs
    )
SELECT * FROM cte WHERE Row_Number <> 1; 

Ergebnis:

DogId FirstName LastName Row_Number----- --------- -------- ----------2 Bark Smith 2 6 Wag Johnson 2 7 Wag Johnson 3 

Dadurch werden Nicht-Duplikate aus der Ausgabe ausgeschlossen, und es wird eine Zeile jedes Duplikats aus der Ausgabe ausgeschlossen.

Option 10

Hier ist eine andere Möglichkeit, dieselbe Ausgabe wie im vorherigen Beispiel zu erhalten:

SELECT * FROM Dogs 
WHERE DogId IN (
    SELECT DogId FROM Dogs 
    EXCEPT SELECT MIN(DogId) FROM Dogs 
    GROUP BY FirstName, LastName
    ); 

Ergebnis:

HundId Vorname Nachname ----- --------- -------- 2 Bark Smith 6 Wag Johnson 7 Wag Johnson 

Option 11

Hier ist noch eine weitere Option, um Duplikate aus unserer Tabelle auszuwählen:

SELECT * 
FROM Dogs d1, Dogs d2 
WHERE d1.FirstName = d2.FirstName 
AND d1.LastName = d2.LastName
AND d1.DogId <> d2.DogId 
AND d1.DogId = (
    SELECT MAX(DogId) 
    FROM Dogs d3 
    WHERE d3.FirstName = d1.FirstName 
    AND d3.LastName = d1.LastName
); 

Ergebnis:

DogId Vorname Nachname DogId Vorname Nachname----- --------- -------- ----- --------- ----- ---2 Bark Smith 1 Bark Smith 7 Wag Johnson 5 Wag Johnson 7 Wag Johnson 6 Wag Johnson