Mysql
 sql >> Baza danych >  >> RDS >> Mysql

7 sposobów na znalezienie zduplikowanych wierszy, ignorując klucz podstawowy w MySQL

Oto siedem sposobów zwracania zduplikowanych wierszy w MySQL, gdy te wiersze mają klucz podstawowy lub inną kolumnę unikatowego identyfikatora.

Przykładowe dane

W naszych przykładach użyjemy następujących danych:

DROP TABLE IF EXISTS Dogs;
CREATE TABLE Dogs (
    DogId int PRIMARY KEY NOT NULL,
    FirstName varchar(50),
    LastName varchar(50)
    );

INSERT INTO Dogs VALUES
    (1, 'Bark', 'Smith'),
    (2, 'Bark', 'Smith'),
    (3, 'Woof', 'Jones'),
    (4, 'Ruff', 'Robinson'),
    (5, 'Wag', 'Johnson'),
    (6, 'Wag', 'Johnson'),
    (7, 'Wag', 'Johnson');
SELECT * FROM Dogs;

Wynik:

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

Zduplikowane wiersze mają dokładnie te same wartości we wszystkich kolumnach z wyjątkiem ich kolumny klucza podstawowego/unikalnego identyfikatora.

Pierwsze dwa wiersze są duplikatami (z wyjątkiem DogId kolumna, która jest kluczem podstawowym tabeli i zawiera unikatową wartość we wszystkich wierszach). Ostatnie trzy wiersze również są duplikatami (z wyjątkiem DogId kolumna).

Kolumna klucza podstawowego zapewnia, że ​​nie ma zduplikowanych wierszy, co zwykle jest dobrą rzeczą w systemach RDBMS. Jednak z definicji oznacza to, że nie ma duplikatów. W naszym przypadku kolumna klucza podstawowego jest liczbą rosnącą, a jej wartość nie ma znaczenia i nie jest istotna. Dlatego musimy zignorować ten wiersz, jeśli chcemy znaleźć duplikaty w kolumnach, które istotne.

Opcja 1

Naszą pierwszą opcją jest użycie GROUP BY klauzula, aby pogrupować kolumny według ich znaczących kolumn, a następnie użyj COUNT() funkcja zwracająca liczbę identycznych wierszy:

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

Wynik:

+-----------+----------+-------+
| FirstName | LastName | Count |
+-----------+----------+-------+
| Bark      | Smith    |     2 |
| Woof      | Jones    |     1 |
| Ruff      | Robinson |     1 |
| Wag       | Johnson  |     3 |
+-----------+----------+-------+

Udało nam się zignorować kolumnę klucza podstawowego, pomijając ją w naszym zapytaniu.

Wynik mówi nam, że istnieją dwa wiersze zawierające Bark Smith i trzy wiersze zawierające Wag Johnson. Są to duplikaty (lub trzy egzemplarze w przypadku Wag Johnson). Pozostałe dwa wiersze nie mają żadnych duplikatów.

Opcja 2

Możemy wykluczyć nieduplikaty z danych wyjściowych za pomocą HAVING klauzula:

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

Wynik:

+-----------+----------+-------+
| FirstName | LastName | Count |
+-----------+----------+-------+
| Bark      | Smith    |     2 |
| Wag       | Johnson  |     3 |
+-----------+----------+-------+

Opcja 3

Możemy również sprawdzić duplikaty w połączonych kolumnach. Na przykład możemy użyć CONCAT() do łączenia naszych dwóch kolumn użyj funkcji DISTINCT słowa kluczowego, aby uzyskać różne wartości, a następnie użyj COUNT() funkcja zwracająca liczbę:

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

Wynik:

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

Opcja 4

Alternatywnie możemy użyć ROW_NUMBER() funkcja z PARTITION BY klauzula:

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

Wynik:

+-------+-----------+----------+----+
| DogId | FirstName | LastName | rn |
+-------+-----------+----------+----+
|     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 |
+-------+-----------+----------+----+

Tworzy to nową kolumnę z numerem wiersza, który zwiększa się za każdym razem, gdy pojawia się duplikat, ale resetuje się ponownie, gdy pojawia się unikalny wiersz

Ta technika zapewnia możliwą korzyść, ponieważ nie musimy grupować wyników. Oznacza to, że możemy zobaczyć każdy zduplikowany wiersz, w tym jego kolumnę z unikalnym identyfikatorem.

Opcja 5

Możemy użyć poprzedniego przykładu jako wspólnego wyrażenia tabelowego w większym zapytaniu:

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

Wynik:

+-------+-----------+----------+----+
| DogId | FirstName | LastName | rn |
+-------+-----------+----------+----+
|     2 | Bark      | Smith    |  2 |
|     6 | Wag       | Johnson  |  2 |
|     7 | Wag       | Johnson  |  3 |
+-------+-----------+----------+----+

Ta technika wyklucza z danych wyjściowych nieduplikaty i jeden wiersz każdego duplikatu z danych wyjściowych.

To zapytanie może służyć jako prekursor operacji usuwania duplikatów. Może nam pokazać, co zostanie usunięte, jeśli zdecydujemy się usunąć duplikaty. Aby usunąć duplikat tabeli, wystarczy zastąpić ostatni SELECT * z DELETE .

Opcja 6

Oto bardziej zwięzły sposób uzyskania tego samego wyniku, co w poprzednim przykładzie:

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

Wynik:

+-------+-----------+----------+
| DogId | FirstName | LastName |
+-------+-----------+----------+
|     2 | Bark      | Smith    |
|     6 | Wag       | Johnson  |
|     7 | Wag       | Johnson  |
+-------+-----------+----------+

Ta technika nie wymaga od nas generowania oddzielnego numeru wiersza za pomocą ROW_NUMBER() jak w poprzednim przykładzie.

Możemy również zastąpić SELECT * z DELETE aby usunąć duplikaty.

Opcja 7

I na koniec jeszcze jedna opcja zwracania duplikatów:

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
);

Wynik:

+-------+-----------+----------+-------+-----------+----------+
| DogId | FirstName | LastName | DogId | FirstName | LastName |
+-------+-----------+----------+-------+-----------+----------+
|     2 | Bark      | Smith    |     1 | Bark      | Smith    |
|     7 | Wag       | Johnson  |     5 | Wag       | Johnson  |
|     7 | Wag       | Johnson  |     6 | Wag       | Johnson  |
+-------+-----------+----------+-------+-----------+----------+

  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Błąd instalacji Ruby gem mysql2

  2. PDO otrzyma ostatni wstawiony identyfikator

  3. CURRENT_DATE Przykłady – MySQL

  4. Sortowanie według daty i godziny w porządku malejącym?

  5. Jak wyłączyć sprawdzanie klucza obcego w MySQL?