MariaDB
 sql >> Datenbank >  >> RDS >> MariaDB

7 Möglichkeiten, doppelte Zeilen zurückzugeben, die einen Primärschlüssel in MariaDB haben

Hier sind sieben Möglichkeiten, doppelte Zeilen in MariaDB zurückzugeben, wenn diese Zeilen einen -Primärschlüssel oder eine andere eindeutige Kennungsspalte haben.

Daher haben die doppelten Zeilen in allen Spalten genau die gleichen Werte, mit Ausnahme ihrer 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 normalerweise in RDBMSs eine gute Sache ist. Per Definition bedeutet dies jedoch, dass es keine Duplikate gibt. In unserem Fall ist die Primärschlüsselspalte eine aufsteigende Zahl, und ihr Wert hat keine Bedeutung und ist nicht signifikant. Daher müssen wir diese Zeile ignorieren, wenn wir Duplikate in den vorhandenen Spalten finden wollen von Bedeutung.

Möglichkeit 1

Wir können den GROUP BY verwenden -Klausel, um die Spalten nach ihren signifikanten Spalten zu gruppieren, und verwenden Sie dann den 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 |
+-----------+----------+-------+
| Bark      | Smith    |     2 |
| Ruff      | Robinson |     1 |
| Wag       | Johnson  |     3 |
| Woof      | Jones    |     1 |
+-----------+----------+-------+

Wir konnten die Primärschlüsselspalte ausschließen, indem wir sie aus unserer Abfrage wegließen.

Das Ergebnis sagt uns, dass es zwei Zeilen mit Bark Smith und drei Zeilen mit Wag Johnson 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 |
+-----------+----------+-------+
| Bark      | Smith    |     2 |
| Wag       | Johnson  |     3 |
+-----------+----------+-------+

Möglichkeit 3

Es ist auch möglich, verkettete Spalten auf Duplikate zu prüfen. Zum Beispiel können wir den CONCAT() verwenden 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 |
+---------------+-------+
| Bark Smith    |     2 |
| Ruff Robinson |     1 |
| Wag Johnson   |     3 |
| Woof Jones    |     1 |
+---------------+-------+

Option 4

Wir können die ROW_NUMBER() verwenden Funktion mit dem PARTITION BY Klausel:

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 |
|     6 | Wag       | Johnson  |          1 |
|     5 | Wag       | Johnson  |          2 |
|     7 | Wag       | Johnson  |          3 |
|     3 | Woof      | Jones    |          1 |
+-------+-----------+----------+------------+

Dadurch wird eine neue Spalte mit einer Zeilennummer erstellt, die jedes Mal erhöht wird, wenn ein Duplikat vorhanden ist, aber wieder zurückgesetzt wird, wenn eine eindeutige Zeile vorhanden ist.

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 |
|     5 | 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.

Diese Abfrage könnte als Vorläufer einer Deduplizierungsoperation verwendet werden. Es kann uns zeigen, was gelöscht wird, wenn wir uns entscheiden, Duplikate zu löschen. Um die Tabelle zu deduplizieren, müssen wir lediglich das letzte SELECT * ersetzen mit DELETE .

Option 6

Hier ist ein prägnanterer 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 |
+-------+-----------+----------+
|     2 | Bark      | Smith    |
|     6 | Wag       | Johnson  |
|     7 | Wag       | Johnson  |
+-------+-----------+----------+

Dieses Beispiel erfordert keine Generierung unserer eigenen separaten Zeilennummer.

Wir können SELECT * ersetzen mit DELETE um die Duplikate zu löschen.

Option 7

Und schließlich ist hier eine weitere Option zum Zurückgeben von Duplikaten:

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  |
+-------+-----------+----------+-------+-----------+----------+