sql >> Databasteknik >  >> RDS >> PostgreSQL

7 sätt att hitta dubbletter av rader i PostgreSQL medan du ignorerar den primära nyckeln

Här är sju sätt att returnera dubbletter av rader i PostgreSQL när dessa rader har en primärnyckel eller annan unik identifierarkolumn.

Det betyder att dubblettraderna delar exakt samma värden i alla kolumner med undantag för deras primärnyckel/unika ID-kolumn.

Exempeldata

Vi använder följande data för våra exempel:

SELECT * FROM Dogs;

Resultat:

 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 två första raderna är dubbletter (förutom DogId kolumn, som är tabellens primärnyckel och innehåller ett unikt värde över alla rader). De sista tre raderna är också dubbletter (förutom DogId kolumn).

Primärnyckelkolumnen säkerställer att det inte finns några dubbletter av rader, vilket är god praxis i RDBMS, eftersom primärnycklar hjälper till att framtvinga dataintegritet. Men eftersom primärnycklar förhindrar dubbletter av rader har de potential att störa vår förmåga att hitta dubbletter.

I vår tabell ovan är primärnyckelkolumnen ett ökande tal, och dess värde har ingen betydelse och är inte signifikant. Vi måste därför ignorera den raden om vi vill hitta dubbletter i de andra kolumnerna.

Alternativ 1

Vi kan använda SQL GROUP BY sats för att gruppera kolumnerna efter deras signifikanta kolumner, använd sedan COUNT() funktion för att returnera antalet identiska rader:

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

Resultat:

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

Här uteslöt vi primärnyckelkolumnen genom att utelämna den från vår fråga.

Resultatet berättar att det finns tre rader som innehåller Wag Johnson och två rader som innehåller Bark Smith. Dessa är dubbletter (eller triplikat i fallet med Wag Johnson). De andra två raderna har inga dubbletter.

Alternativ 2

Vi kan utesluta icke-duplikat från utdata med HAVING klausul:

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

Resultat:

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

Alternativ 3

Här är ett exempel på hur du söker efter dubbletter på sammanlänkade kolumner. I det här fallet använder vi CONCAT() funktion för att sammanfoga våra två kolumner, använd DISTINCT nyckelord för att få distinkta värden, använd sedan COUNT() funktion för att returnera antalet:

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

Resultat:

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

Alternativ 4

Vi kan alternativt använda ROW_NUMBER() fönsterfunktion:

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

Resultat:

 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

Använda PARTITION klausul resulterar i att en ny kolumn läggs till, med ett radnummer som ökar varje gång det finns en dubblett, men återställs igen när det finns en unik rad.

I det här fallet grupperar vi inte resultaten, vilket innebär att vi kan se varje dubblettrad, inklusive dess unika identifierarkolumn.

Alternativ 5

Vi kan också använda föregående exempel som ett vanligt tabelluttryck i en större fråga:

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;

Resultat:

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

Detta utesluter icke-dubbletter från utgången, och det utesluter en rad av varje dubblett från utgången. Med andra ord visar den bara de överflödiga raderna från dubbletterna. Dessa rader är främsta kandidater för att raderas i en de-dupingoperation.

Alternativ 6

Här är ett mer kortfattat sätt att få samma utdata som föregående exempel:

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

Resultat:

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

En skillnad mellan det här exemplet och det föregående är att det här exemplet inte kräver att vi genererar vårt eget separata radnummer.

Alternativ 7

Här är ytterligare ett alternativ för att returnera dubbletter av rader i 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
);

Resultat:

 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. Hur man hittar standardfilplatsen för datafiler och loggfiler i SQL Server

  2. Hur man skapar en användare och beviljar behörigheter i Oracle

  3. ogiltig bytesekvens för kodning av UTF8

  4. Metadata om PL/SQL-posttyper på paketnivå