Her er elleve muligheder for at returnere duplikerede rækker i SQLite, når disse rækker har en primær nøgle eller en anden unik identifikatorkolonne (men du vil ignorere den primære nøgle).
Det betyder, at de duplikerede rækker deler nøjagtigt de samme værdier på tværs af alle kolonner med undtagelse af deres primære nøgle/unikke id-kolonne.
Eksempel på data
Vi bruger følgende data til vores eksempler:
SELECT * FROM Dogs;
Resultat:
DogId Fornavn Efternavn----- ---------- --------1 Bark Smith 2 Bark Smith 3 Woof Jones 4 Ruff Robinson5 Wag Johnson 6 Wag Johnson 7 Wag JohnsonDe første to rækker er dubletter (undtagen
DogId
kolonne, som er tabellens primære nøgle og indeholder en unik værdi på tværs af alle rækker). De sidste tre rækker er også dubletter (bortset fraDogId
kolonne).Primærnøglekolonnen sikrer, at der ikke er dublerede rækker, hvilket er god praksis i RDBMS'er, fordi primærnøgler hjælper med at håndhæve dataintegritet. Men fordi primærnøgler forhindrer duplikerede rækker, har de potentialet til at forstyrre vores evne til at finde dubletter.
I vores tabel ovenfor er den primære nøglekolonne et stigende tal, og dens værdi har ingen betydning og er ikke signifikant. Vi er derfor nødt til at ignorere den række, hvis vi vil finde dubletter i de andre kolonner.
Mulighed 1
Vi kan køre en forespørgsel med
GROUP BY
klausul for at gruppere kolonnerne efter deres signifikante kolonner, brug derefterCOUNT()
funktion for at returnere antallet af identiske rækker:SELECT FirstName, LastName, COUNT(*) AS Count FROM Dogs GROUP BY FirstName, LastName ORDER BY Count DESC;
Resultat:
Fornavn Efternavn Antal--------- -------- -----Wag Johnson 3 Bark Smith 2 Ruff Robinson 1 Woof Jones 1Her udelukkede vi den primære nøglekolonne ved at udelade den fra vores forespørgsel. Vi har også bestilt det efter antal i faldende rækkefølge, så dubletterne vises først.
Resultatet fortæller os, at der er tre rækker indeholdende Wag Johnson og to rækker indeholdende Bark Smith. Disse er dubletter (eller triplikater i tilfældet med Wag Johnson). De to andre rækker har ingen dubletter.
Mulighed 2
Vi kan bruge koden
HAVING
klausul for at udelukke ikke-duplikater fra outputtet:SELECT FirstName, LastName, COUNT(*) AS Count FROM Dogs GROUP BY FirstName, LastName HAVING COUNT(*) > 1 ORDER BY Count DESC;
Resultat:
Fornavn Efternavn Antal--------- -------- -----Wag Johnson 3 Bark Smith 2Mulighed 3
Her er et eksempel på kontrol for dubletter på sammenkædede kolonner. I dette tilfælde bruger vi
DISTINCT
søgeord for at få forskellige værdier, og brug derefterCOUNT()
funktion for at returnere antallet: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 1Mulighed 4
Som standard har hver række i SQLite en speciel kolonne, normalt kaldet
rowid
, der entydigt identificerer den pågældende række i tabellen. Medmindre det eksplicit er blevet fjernet fra tabellen, kan du bruge dette som en unik identifikator for hver række.Vi kan derfor bruge
rowid
i vores forespørgsel: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 Fornavn Efternavn----- ---------- --------2 Bark Smith 6 Wag Johnson 7 Wag JohnsonVi kunne erstatte
SELECT *
medDELETE
at udføre en de-duping operation på bordet.Bemærk, at vi kunne have brugt
DogId
kolonne (vores primære nøgle) i stedet forrowid
hvis vi ville. Når det er sagt,rowid
kan være nyttigt, hvis du af en eller anden grund ikke kan bruge primærnøglekolonnen, eller hvis tabellen ikke har en primærnøgle.Mulighed 5
Her er en anden forespørgsel, der bruger
rowid
:SELECT * FROM Dogs WHERE rowid > ( SELECT MIN(rowid) FROM Dogs d2 WHERE Dogs.FirstName = d2.FirstName AND Dogs.LastName = d2.LastName );
Resultat:
DogId Fornavn Efternavn----- ---------- --------2 Bark Smith 6 Wag Johnson 7 Wag JohnsonSom med det foregående eksempel kunne vi erstatte
SELECT *
medDELETE
for at slette de duplikerede rækker.Mulighed 6
De to
rowid
mulighederne ovenfor er gode, hvis du fuldstændig skal ignorere den primære nøgle i din forespørgsel (eller hvis du slet ikke har en primær nøglekolonne). Men som nævnt er der stadig mulighed for at erstatterowid
med den primære nøglekolonne – i vores tilfældeDogId
kolonne: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 Fornavn Efternavn----- ---------- --------2 Bark Smith 6 Wag Johnson 7 Wag JohnsonMulighed 7
Og her er den anden forespørgsel med
rowid
erstattet afDogId
kolonne:SELECT * FROM Dogs WHERE DogId > ( SELECT MIN(DogId) FROM Dogs d2 WHERE Dogs.FirstName = d2.FirstName AND Dogs.LastName = d2.LastName );
Resultat:
DogId Fornavn Efternavn----- ---------- --------2 Bark Smith 6 Wag Johnson 7 Wag JohnsonMulighed 8
En anden måde at gøre det på er at bruge
ROW_NUMBER()
vinduesfunktion:SELECT *, ROW_NUMBER() OVER ( PARTITION BY FirstName, LastName ORDER BY FirstName, LastName ) AS Row_Number FROM Dogs;
Resultat:
DogId Fornavn Efternavn Række_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 1Brug af
PARTITION
klausul resulterer i, at der tilføjes en ny kolonne med et rækkenummer, der stiger hver gang der er en dublet, men nulstilles igen, når der er en unik række.I dette tilfælde grupperer vi ikke resultaterne, hvilket betyder, at vi kan se hver dubletrække, inklusive dens unikke identifikatorkolonne.
Mulighed 9
Vi kan også bruge det foregående eksempel som et almindeligt tabeludtryk i en større forespørgsel:
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 Fornavn Efternavn Række_Number----- ---------- -------- ----------2 Bark Smith 2 6 Wag Johnson 2 7 Wag Johnson 3Det udelukker ikke-duplikater fra outputtet, og det udelukker en række af hver dublet fra outputtet.
Mulighed 10
Her er en anden måde at få det samme output som det forrige eksempel:
SELECT * FROM Dogs WHERE DogId IN ( SELECT DogId FROM Dogs EXCEPT SELECT MIN(DogId) FROM Dogs GROUP BY FirstName, LastName );
Resultat:
DogId Fornavn Efternavn----- ---------- --------2 Bark Smith 6 Wag Johnson 7 Wag JohnsonMulighed 11
Her er endnu en mulighed for at vælge dubletter fra vores tabel:
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:
HundeId Fornavn Efternavn HundeId Fornavn Efternavn----- ---------- -------- ----- ---------- ----- ---2 Bark Smith 1 Bark Smith 7 Wag Johnson 5 Wag Johnson 7 Wag Johnson 6 Wag Johnson