PostgreSQL
 sql >> Baza danych >  >> RDS >> PostgreSQL

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

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

Oznacza to, że zduplikowane wiersze mają dokładnie te same wartości we wszystkich kolumnach z wyjątkiem ich kolumny klucza podstawowego/unikalnego identyfikatora.

Przykładowe dane

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

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

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 jest dobrą praktyką w systemach RDBMS, ponieważ klucze podstawowe pomagają wymusić integralność danych. Ale ponieważ klucze podstawowe zapobiegają duplikowaniu wierszy, mogą one potencjalnie zakłócać naszą zdolność do znajdowania duplikatów.

W naszej tabeli powyżej 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 innych kolumnach.

Opcja 1

Możemy użyć SQL 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 
-----------+----------+-------
 Ruff      | Robinson |     1
 Wag       | Johnson  |     3
 Woof      | Jones    |     1
 Bark      | Smith    |     2

Tutaj wykluczyliśmy kolumnę klucza podstawowego, pomijając ją w naszym zapytaniu.

Wynik mówi nam, że istnieją trzy wiersze zawierające Wag Johnson i dwa wiersze zawierające Bark Smith. 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 
-----------+----------+-------
 Wag       | Johnson  |     3
 Bark      | Smith    |     2

Opcja 3

Oto przykład sprawdzania duplikatów w połączonych kolumnach. W tym przypadku używamy 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 
---------------+-------
 Wag Johnson   |     3
 Ruff Robinson |     1
 Woof Jones    |     1
 Bark Smith    |     2

Opcja 4

Alternatywnie możemy użyć ROW_NUMBER() funkcja okna:

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

Wynik:

 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

Korzystanie z PARTITION klauzula powoduje dodanie nowej kolumny z numerem wiersza, który zwiększa się za każdym razem, gdy pojawia się duplikat, ale resetuje się ponownie, gdy istnieje unikalny wiersz.

W tym przypadku nie grupujemy wyników, co oznacza, że ​​możemy zobaczyć każdy zduplikowany wiersz, w tym jego kolumnę z unikalnym identyfikatorem.

Opcja 5

Możemy również 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 Row_Number
        FROM Dogs
    )
SELECT * FROM cte WHERE Row_Number <> 1;

Wynik:

 dogid | firstname | lastname | row_number 
-------+-----------+----------+------------
     2 | Bark      | Smith    |          2
     6 | Wag       | Johnson  |          2
     7 | Wag       | Johnson  |          3

Wyklucza to nieduplikaty z danych wyjściowych i wyklucza jeden wiersz każdego duplikatu z danych wyjściowych. Innymi słowy, pokazuje tylko nadmiarowe wiersze z duplikatów. Te wiersze są głównymi kandydatami do usunięcia w operacji usuwania duplikatów.

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 
    EXCEPT SELECT MIN(DogId) FROM Dogs 
    GROUP BY FirstName, LastName
    );

Wynik:

 dogid | firstname | lastname 
-------+-----------+----------
     6 | Wag       | Johnson
     2 | Bark      | Smith
     7 | Wag       | Johnson

Jedną z różnic między tym przykładem a poprzednim jest to, że ten przykład nie wymaga generowania własnego oddzielnego numeru wiersza.

Opcja 7

Oto kolejna opcja zwracania zduplikowanych wierszy w Postgresie:

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. PostgreSQL:serial a tożsamość

  2. Błąd podczas próby uruchomienia pgAdmin4

  3. Pobierz ostatni dzień miesiąca w PostgreSQL

  4. Przechowywanie json, jsonb, hstore, xml, enum, ipaddr itp. kończy się niepowodzeniem, ponieważ kolumna x jest typu json, ale wyrażenie ma charakter zmienny

  5. Zdobądź drzewo rodziców + dzieci z pg-obietnicą