Hier sind sieben Möglichkeiten, doppelte Zeilen in PostgreSQL zurückzugeben, wenn diese Zeilen einen Primärschlüssel oder eine andere eindeutige Kennungsspalte haben.
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:
dogid | firstname | lastname -------+-----------+---------- 1 | Bark | Smith 2 | Bark | Smith 3 | Woof | Jones 4 | Ruff | Robinson 5 | 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 den SQL GROUP BY
verwenden -Klausel, um die Spalten nach ihren signifikanten Spalten zu gruppieren, und verwenden Sie dann COUNT()
Funktion, um die Anzahl identischer Zeilen zurückzugeben:
SELECT
FirstName,
LastName,
COUNT(*) AS Count
FROM Dogs
GROUP BY FirstName, LastName;
Ergebnis:
firstname | lastname | count -----------+----------+------- Ruff | Robinson | 1 Wag | Johnson | 3 Woof | Jones | 1 Bark | Smith | 2
Hier haben wir die Primärschlüsselspalte ausgeschlossen, indem wir sie aus unserer Abfrage weggelassen haben.
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
Mit dem HAVING
können wir Nicht-Duplikate von der Ausgabe ausschließen Klausel:
SELECT
FirstName,
LastName,
COUNT(*) AS Count
FROM Dogs
GROUP BY FirstName, LastName
HAVING COUNT(*) > 1;
Ergebnis:
firstname | lastname | count -----------+----------+------- 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 CONCAT()
Um unsere beiden Spalten zu verketten, verwenden Sie die Funktion DISTINCT
Schlüsselwort, um unterschiedliche Werte zu erhalten, und verwenden Sie dann COUNT()
Funktion, um die Zählung zurückzugeben:
SELECT
DISTINCT CONCAT(FirstName, ' ', LastName) AS DogName,
COUNT(*) AS Count
FROM Dogs
GROUP BY CONCAT(FirstName, ' ', LastName);
Ergebnis:
dogname | count ---------------+------- Wag Johnson | 3 Ruff Robinson | 1 Woof Jones | 1 Bark Smith | 2
Option 4
Wir können alternativ die ROW_NUMBER()
verwenden 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 5
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. Mit anderen Worten, es werden nur die überschüssigen Zeilen der Duplikate angezeigt. Diese Zeilen sind die besten Kandidaten, um bei einem Deduplizierungsvorgang gelöscht zu werden.
Option 6
Hier ist ein kürzerer Weg, um die gleiche 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:
dogid | firstname | lastname -------+-----------+---------- 6 | Wag | Johnson 2 | Bark | Smith 7 | Wag | Johnson
Ein Unterschied zwischen diesem Beispiel und dem vorherigen besteht darin, dass für dieses Beispiel keine eigene separate Zeilennummer generiert werden muss.
Option 7
Hier ist noch eine weitere Option zum Zurückgeben doppelter Zeilen in Postgres:
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 | firstname | lastname | dogid | firstname | lastname -------+-----------+----------+-------+-----------+---------- 2 | Bark | Smith | 1 | Bark | Smith 7 | Wag | Johnson | 5 | Wag | Johnson 7 | Wag | Johnson | 6 | Wag | Johnson