Oracle
 sql >> база данни >  >> RDS >> Oracle

6 начина за изтриване на дублиращи се редове, които имат първичен ключ в Oracle

Ето някои опции за изтриване на дублиращи се редове от таблица в Oracle Database, когато тези редове имат първичен ключ или колона с уникален идентификатор.

В такива случаи първичният ключ трябва да се игнорира при сравняване на дублиращи се редове (поради факта, че първичните ключове съдържат уникални стойности).

Примерни данни

Нашите примери използват следните данни:

SELECT * FROM Dogs;

Резултат:

ДОГИД FIRSTNAME LASTNAME
1 Кора Смит
2 Кора Смит
3 Уф Джоунс
4 Ръф Робинзон
5 Размахване Джонсън
6 Размахване Джонсън
7 Размахване Джонсън

Можем да видим, че първите два реда са дублирани, както и последните три реда.

DogId колоната съдържа уникални стойности (тъй като това е първичен ключ на таблицата), но ние игнорираме тази колона, когато сравняваме дубликати. Често може да се окаже, че се налага да премахнете дублирането на таблици, които съдържат първични ключове, така че следните примери могат да се използват за това.

Опция 1

Ето първата ни опция за премахване на дубликата на горната таблица:

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

SELECT * FROM Dogs;

Резултат:

ДОГИД FIRSTNAME LASTNAME
1 Кора Смит
3 Уф Джоунс
4 Ръф Робинзон
5 Размахване Джонсън

Дубликатите са премахнати (но остава един ред от всеки дубликат).

Като алтернатива можем да използваме MAX() функция вместо MIN() функция за промяна на кои редове се изтриват.

Опция 2

В този пример (и следващите примери) ще приемем, че таблицата е възстановена в първоначалното си състояние (с дубликатите).

Ето още един пример, който премахва дублирането на таблицата и след това избира останалите редове:

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;

Резултат:

ДОГИД FIRSTNAME LASTNAME
2 Кора Смит
3 Уф Джоунс
4 Ръф Робинзон
7 Размахване Джонсън

Забележете, че използвах MAX() функция вместо MIN() който използвах в предишния пример. Можем да видим влиянието, което това оказва върху операцията за премахване на дуппинга. Той изтри различни редове от таблицата.

Опция 3

Ето опция, която не изисква използването на MIN() или 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;

Резултат:

ДОГИД FIRSTNAME LASTNAME
1 Кора Смит
3 Уф Джоунс
4 Ръф Робинзон
5 Размахване Джонсън

Опция 4

Ето още една опция:

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

SELECT * FROM Dogs;

Резултат:

ДОГИД FIRSTNAME LASTNAME
1 Кора Смит
3 Уф Джоунс
4 Ръф Робинзон
5 Размахване Джонсън

Опция 5

Всеки ред в Oracle има rowid псевдоколона, която връща адреса на реда. rowid е уникален идентификатор за редове в таблицата и обикновено неговата стойност уникално идентифицира ред в базата данни (въпреки че е важно да се отбележи, че редовете в различни таблици, които се съхраняват заедно в един и същ клъстер, могат да имат един и същ rowid ).

Следователно можем да използваме rowid в нашата заявка вместо DogId колона:

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;

Резултат:

ДОГИД FIRSTNAME LASTNAME
1 Кора Смит
3 Уф Джоунс
4 Ръф Робинзон
5 Размахване Джонсън

Въпреки че този пример може да изглежда малко излишен, като се има предвид, че вече имаме колона с първичен ключ, може да има случаи, в които предпочитате да използвате rowid . rowid може да бъде полезно, ако по някаква причина не можете да използвате колоната с първичен ключ или ако таблицата няма първичен ключ. Освен това в документацията на Oracle се споменава, че rowid стойностите са най-бързият начин за достъп до един ред.

Опция 6

И ето другия пример, но с rowid вместо първичния ключ:

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

SELECT * FROM Dogs;

Резултат:

ДОГИД FIRSTNAME LASTNAME
1 Кора Смит
3 Уф Джоунс
4 Ръф Робинзон
5 Размахване Джонсън

  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Изчисляване на разликата между две времеви марки в Oracle в милисекунди

  2. Как да шифровате парола в Oracle?

  3. Кръстосано присъединяване в Oracle

  4. Oracle JDBC ojdbc6 Jar като зависимост на Maven

  5. Как да проверите всяко липсващо число от поредица от числа?