sql >> Database >  >> RDS >> PostgreSQL

7 manieren om dubbele rijen in PostgreSQL te vinden terwijl de primaire sleutel wordt genegeerd

Hier zijn zeven manieren om dubbele rijen in PostgreSQL te retourneren wanneer die rijen een primaire sleutel of een andere unieke identificatiekolom hebben.

Dit betekent dat de dubbele rijen exact dezelfde waarden delen in alle kolommen, met uitzondering van hun primaire sleutel/unieke ID-kolom.

Voorbeeldgegevens

We gebruiken de volgende gegevens voor onze voorbeelden:

SELECT * FROM Dogs;

Resultaat:

 dogid | firstname | lastname 
-------+-----------+----------
     1 | Bark      | Smith
     2 | Bark      | Smith
     3 | Woof      | Jones
     4 | Ruff      | Robinson
     5 | Wag       | Johnson
     6 | Wag       | Johnson
     7 | Wag       | Johnson

De eerste twee rijen zijn duplicaten (behalve de DogId kolom, de primaire sleutel van de tabel, en bevat een unieke waarde voor alle rijen). De laatste drie rijen zijn ook duplicaten (behalve de DogId kolom).

De primaire sleutelkolom zorgt ervoor dat er geen dubbele rijen zijn, wat een goede gewoonte is in RDBMS'en, omdat primaire sleutels helpen de gegevensintegriteit af te dwingen. Maar omdat primaire sleutels dubbele rijen voorkomen, kunnen ze ons vermogen om dubbele rijen te vinden belemmeren.

In onze tabel hierboven is de primaire sleutelkolom een ​​oplopend getal, en de waarde ervan heeft geen betekenis en is niet significant. We moeten die rij dus negeren als we duplicaten willen vinden in de andere kolommen.

Optie 1

We kunnen de SQL GROUP BY . gebruiken clausule om de kolommen te groeperen op hun significante kolommen, gebruik dan de COUNT() functie om het aantal identieke rijen terug te geven:

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

Resultaat:

 firstname | lastname | count 
-----------+----------+-------
 Ruff      | Robinson |     1
 Wag       | Johnson  |     3
 Woof      | Jones    |     1
 Bark      | Smith    |     2

Hier hebben we de primaire sleutelkolom uitgesloten door deze uit onze zoekopdracht weg te laten.

Het resultaat vertelt ons dat er drie rijen zijn met Wag Johnson en twee rijen met Bark Smith. Dit zijn duplicaten (of drievoud in het geval van Wag Johnson). De andere twee rijen hebben geen dubbele rijen.

Optie 2

We kunnen niet-duplicaten uitsluiten van de uitvoer met de HAVING clausule:

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

Resultaat:

 firstname | lastname | count 
-----------+----------+-------
 Wag       | Johnson  |     3
 Bark      | Smith    |     2

Optie 3

Hier is een voorbeeld van het controleren op duplicaten in aaneengeschakelde kolommen. In dit geval gebruiken we de CONCAT() functie om onze twee kolommen samen te voegen, gebruik de DISTINCT zoekwoord om verschillende waarden te krijgen, gebruik dan de COUNT() functie om de telling terug te geven:

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

Resultaat:

    dogname    | count 
---------------+-------
 Wag Johnson   |     3
 Ruff Robinson |     1
 Woof Jones    |     1
 Bark Smith    |     2

Optie 4

We kunnen ook de ROW_NUMBER() . gebruiken vensterfunctie:

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

Resultaat:

 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

De PARTITION . gebruiken clausule resulteert in het toevoegen van een nieuwe kolom, met een rijnummer dat wordt verhoogd elke keer dat er een duplicaat is, maar opnieuw wordt ingesteld wanneer er een unieke rij is.

In dit geval groeperen we de resultaten niet, wat betekent dat we elke dubbele rij kunnen zien, inclusief de unieke ID-kolom.

Optie 5

We kunnen het vorige voorbeeld ook gebruiken als een algemene tabeluitdrukking in een grotere query:

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;

Resultaat:

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

Dit sluit niet-duplicaten uit van de uitvoer en sluit één rij van elk duplicaat uit van de uitvoer. Met andere woorden, het toont alleen de overtollige rijen van de duplicaten. Deze rijen zijn de voornaamste kandidaten om te worden verwijderd bij een ontdubbelingsoperatie.

Optie 6

Hier is een beknoptere manier om dezelfde uitvoer te krijgen als in het vorige voorbeeld:

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

Resultaat:

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

Een verschil tussen dit voorbeeld en het vorige is dat dit voorbeeld niet het genereren van ons eigen aparte rijnummer vereist.

Optie 7

Hier is nog een andere optie voor het retourneren van dubbele rijen 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
);

Resultaat:

 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. Hoe de primaire sleutelreeks van postgres opnieuw in te stellen wanneer deze niet meer synchroon loopt?

  2. 4 manieren om alle weergaven in een MariaDB-database weer te geven

  3. Telkolom bijwerken vanuit gegevens in een andere tabel

  4. Hoe kan ik row_number in Oracle versnellen?