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 JohnsonDe 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örutomDogId
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 sedanCOUNT()
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 1Hä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 2Alternativ 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 sedanCOUNT()
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 1Alternativ 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 JohnsonVi skulle kunna ersätta
SELECT *
medDELETE
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örrowid
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 JohnsonSom med föregående exempel, kunde vi ersätta
SELECT *
medDELETE
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ättarowid
med primärnyckelkolumnen – i vårt fallDogId
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 JohnsonAlternativ 7
Och här är den andra frågan med
rowid
ersatt avDogId
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 JohnsonAlternativ 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 1Anvä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 3Det 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 JohnsonAlternativ 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