sql >> Databasteknik >  >> RDS >> Oracle

6 sätt att ta bort dubbletter av rader som har en primärnyckel i Oracle

Här är några alternativ för att ta bort dubbletter av rader från en tabell i Oracle Database när dessa rader har en primärnyckel eller unik identifierarkolumn.

I sådana fall måste primärnyckeln ignoreras när du jämför dubbletter av rader (på grund av att primärnycklar har unika värden).

Exempeldata

Våra exempel använder följande data:

SELECT * FROM Dogs;

Resultat:

DOGID FIRSTNAME LASTNAME
1 Skall Smith
2 Skall Smith
3 Wuff Jones
4 Ruff Robinson
5 Wag Johnson
6 Wag Johnson
7 Wag Johnson

Vi kan se att de två första raderna är dubbletter, liksom de tre sista raderna.

DogId kolumnen innehåller unika värden (eftersom det är tabellens primärnyckel), men vi ignorerar den kolumnen när vi jämför dubbletter. Du kanske ofta behöver dedupera tabeller som innehåller primärnycklar, och därför kan följande exempel användas för att göra just det.

Alternativ 1

Här är vårt första alternativ för att dedupera tabellen ovan:

DELETE FROM Dogs 
WHERE DogId IN (
    SELECT DogId FROM Dogs 
    MINUS SELECT MIN(DogId) FROM Dogs 
    GROUP BY FirstName, LastName
    );

SELECT * FROM Dogs;

Resultat:

DOGID FIRSTNAME LASTNAME
1 Skall Smith
3 Wuff Jones
4 Ruff Robinson
5 Wag Johnson

Dubbletterna har tagits bort (men en rad av varje duplikat finns kvar).

Vi kan alternativt använda MAX() funktion istället för MIN() funktion för att ändra vilka rader som tas bort.

Alternativ 2

I det här exemplet (och följande exempel) antar vi att tabellen har återställts till sitt ursprungliga tillstånd (med dubbletter).

Här är ett annat exempel som avduperar tabellen och sedan väljer de återstående raderna:

DELETE FROM Dogs WHERE DogId IN (
    SELECT d2.DogId 
    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
    )
);

SELECT * FROM Dogs;

Resultat:

DOGID FIRSTNAME LASTNAME
2 Skall Smith
3 Wuff Jones
4 Ruff Robinson
7 Wag Johnson

Lägg märke till att jag använde MAX() funktion istället för MIN() som jag använde i föregående exempel. Vi kan se vilken inverkan detta har på de-dupingverksamheten. Den tog bort olika rader från tabellen.

Alternativ 3

Här är ett alternativ som inte kräver användning av MIN() eller MAX() :

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

SELECT * FROM Dogs;

Resultat:

DOGID FIRSTNAME LASTNAME
1 Skall Smith
3 Wuff Jones
4 Ruff Robinson
5 Wag Johnson

Alternativ 4

Här är ett annat alternativ:

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

SELECT * FROM Dogs;

Resultat:

DOGID FIRSTNAME LASTNAME
1 Skall Smith
3 Wuff Jones
4 Ruff Robinson
5 Wag Johnson

Alternativ 5

Varje rad i Oracle har en rovid pseudokolumn som returnerar adressen till raden. rovid är en unik identifierare för rader i tabellen, och vanligtvis identifierar dess värde unikt en rad i databasen (även om det är viktigt att notera att rader i olika tabeller som lagras tillsammans i samma kluster kan ha samma radid ).

Vi kan därför använda rovid i vår fråga istället för DogId kolumn:

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

SELECT * FROM Dogs;

Resultat:

DOGID FIRSTNAME LASTNAME
1 Skall Smith
3 Wuff Jones
4 Ruff Robinson
5 Wag Johnson

Även om det här exemplet kan verka lite överflödigt, eftersom vi redan har en primärnyckelkolumn, kan det finnas tillfällen där du föredrar att använda rovid . rovid kan vara användbart om du inte kan använda primärnyckelkolumnen av någon anledning, eller om tabellen inte har en primärnyckel. Oracles dokumentation nämner också att rovid värden är det snabbaste sättet att komma åt en enskild rad.

Alternativ 6

Och här är det andra exemplet, men med rowid istället för primärnyckeln:

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

SELECT * FROM Dogs;

Resultat:

DOGID FIRSTNAME LASTNAME
1 Skall Smith
3 Wuff Jones
4 Ruff Robinson
5 Wag Johnson

  1. Hur man ansluter till MySQL med Microsoft .NET

  2. hur lagrar jag PostgreSQL jsonb med SpringBoot + JPA?

  3. Vilken är ordningen på poster i en tabell med en sammansatt primärnyckel

  4. Hur DAYOFYEAR() fungerar i MariaDB