sql >> Database teknologi >  >> RDS >> SQLite

11 måder at finde dublerede rækker, mens du ignorerer den primære nøgle i SQLite

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 Johnson  

De 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 fra DogId 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 derefter COUNT() 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 1 

Her 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 2 

Mulighed 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 derefter COUNT() 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 1 

Mulighed 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 Johnson 

Vi kunne erstatte SELECT * med DELETE 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 for rowid 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 Johnson 

Som med det foregående eksempel kunne vi erstatte SELECT * med DELETE 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 erstatte rowid med den primære nøglekolonne – i vores tilfælde DogId 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 Johnson 

Mulighed 7

Og her er den anden forespørgsel med rowid erstattet af DogId 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 Johnson 

Mulighed 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 1 

Brug 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 3 

Det 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 Johnson 

Mulighed 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 

  1. Udforskning af de forskellige begrænsninger i SQL Server

  2. Hvordan finder man forespørgselsudførelsestid i Oracle SQL Developer?

  3. Sådan laver du dynamiske postgres-forberedte erklæringer i PHP

  4. TRUNC(tal) Funktion i Oracle