sql >> Databasteknik >  >> RDS >> SQLite

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

Här är elva alternativ för att returnera dubbletter av rader i SQLite när dessa rader har en primärnyckel eller någon annan unik identifierarkolumn (men du vill ignorera primärnyckeln).

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 Efternamn----- ---------- --------1 Bark Smith 2 Bark Smith 3 Woof Jones 4 Ruff Robinson5 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 köra en fråga med GROUP BY 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
ORDER BY Count DESC; 

Resultat:

FirstName Efternamn Count--------- -------- -----Wag Johnson 3 Bark Smith 2 Ruff Robinson 1 Woof Jones 1 

Här uteslöt vi primärnyckelkolumnen genom att utelämna den från vår fråga. Vi har också beställt det efter antal i fallande ordning, så att dubletterna visas först.

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 använda koden HAVING sats för att utesluta icke-dubbel från utdata:

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

Resultat:

FirstName Efternamn 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 DISTINCT nyckelord för att få distinkta värden, använd sedan COUNT() funktion för att returnera antalet:

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

Resultat:

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

Alternativ 4

Som standard har varje rad i SQLite en speciell kolumn, vanligtvis kallad rowid , som unikt identifierar den raden i tabellen. Om den inte uttryckligen har tagits bort från tabellen kan du använda den som en unik identifierare för varje rad.

Vi kan därför använda rowid i vår fråga:

SELECT * FROM Dogs
WHERE EXISTS (
  SELECT 1 FROM Dogs d2 
  WHERE Dogs.FirstName = d2.FirstName
  AND Dogs.LastName = d2.LastName
  AND Dogs.rowid > d2.rowid
); 

Resultat:

DogId FirstName Efternamn----- ---------- --------2 Bark Smith 6 Wag Johnson 7 Wag Johnson 

Vi skulle kunna ersätta SELECT * med DELETE för att utföra en de-duping-operation på bordet.

Observera att vi kunde ha använt DogId kolumnen (vår primärnyckel) istället för rowid om vi ville. Som sagt, rowid kan vara användbart om du inte kan använda primärnyckelkolumnen av någon anledning, eller om tabellen inte har en primärnyckel.

Alternativ 5

Här är en annan fråga som använder rowid :

SELECT * FROM Dogs
WHERE rowid > (
  SELECT MIN(rowid) FROM Dogs d2  
  WHERE Dogs.FirstName = d2.FirstName
  AND Dogs.LastName = d2.LastName
); 

Resultat:

DogId FirstName Efternamn----- ---------- --------2 Bark Smith 6 Wag Johnson 7 Wag Johnson 

Som med föregående exempel, kunde vi ersätta SELECT * med DELETE för att ta bort dubblettraderna.

Alternativ 6

De två rowid alternativen ovan är bra om du helt måste ignorera primärnyckeln i din fråga (eller om du inte har en primärnyckelkolumn alls). Men som nämnts finns det fortfarande möjlighet att ersätta rowid med primärnyckelkolumnen – i vårt fall DogId kolumn:

SELECT * FROM Dogs
WHERE EXISTS (
  SELECT 1 FROM Dogs d2 
  WHERE Dogs.FirstName = d2.FirstName
  AND Dogs.LastName = d2.LastName
  AND Dogs.DogId > d2.DogId
); 

Resultat:

DogId FirstName Efternamn----- ---------- --------2 Bark Smith 6 Wag Johnson 7 Wag Johnson 

Alternativ 7

Och här är den andra frågan med rowid ersatt av DogId kolumn:

SELECT * FROM Dogs
WHERE DogId > (
  SELECT MIN(DogId) FROM Dogs d2  
  WHERE Dogs.FirstName = d2.FirstName
  AND Dogs.LastName = d2.LastName
); 

Resultat:

DogId FirstName Efternamn----- ---------- --------2 Bark Smith 6 Wag Johnson 7 Wag Johnson 

Alternativ 8

Ett annat sätt att göra det är att 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 Förnamn Efternamn Rad_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 9

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 Efternamn Rad_Number----- ---------- -------- ----------2 Bark Smith 2 6 Wag Johnson 2 7 Wag Johnson 3 

Det utesluter icke-dubbel från utdata, och det exkluderar en rad av varje duplikat från utdata.

Alternativ 10

Här är ett annat 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 Efternamn----- ---------- --------2 Bark Smith 6 Wag Johnson 7 Wag Johnson 

Alternativ 11

Här är ännu ett alternativ för att välja dubbletter från vår tabell:

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:

Hund-ID Förnamn Efternamn Hund-ID Förnamn Efternamn----- ---------- -------- ----- ---------- ----- ---2 Bark Smith 1 Bark Smith 7 Wag Johnson 5 Wag Johnson 7 Wag Johnson 6 Wag Johnson 

  1. Kan inte ansluta till MySQL 4.1+ med gammal autentisering

  2. Hur man skapar en tabell i SQL Server

  3. Möt Michal Bar and Me på Microsoft Ignite!

  4. 3 sätt att säkerhetskopiera en SQLite-databas