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

6 начина за избор на дублиращи се редове в Oracle

Следните примери връщат дублиращи се редове от таблица на Oracle Database.

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

Да предположим, че имаме таблица със следните данни:

SELECT * FROM Pets;

Резултат:

PetId  PetName  PetType
-----  -------  -------
1      Wag      Dog    
1      Wag      Dog    
2      Scratch  Cat    
3      Tweet    Bird   
4      Bark     Dog    
4      Bark     Dog    
4      Bark     Dog    

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

Опция 1

Можем да използваме следната заявка, за да видим колко реда са дублирани:

SELECT 
    PetId,
    PetName,
    PetType,
    COUNT(*) AS "Count"
FROM Pets
GROUP BY 
    PetId,
    PetName,
    PetType
ORDER BY PetId;

Резултат:

PETID	PETNAME	PETTYPE	Count
1	Wag	Dog	2
2	Scratch	Cat	1
3	Tweet	Bird	1
4	Bark	Dog	3

Групирахме редовете по всички колони и върнахме броя на редовете за всяка група. Всеки ред с брой по-голям от 1 е дубликат.

Можем да го подредим по брой в низходящ ред, така че редовете с най-много дубликати да се показват първи:

SELECT 
    PetId,
    PetName,
    PetType,
    COUNT(*) AS "Count"
FROM Pets
GROUP BY 
    PetId,
    PetName,
    PetType
ORDER BY Count(*) DESC;

Резултат:

PETID	PETNAME	PETTYPE	Count
4	Bark	Dog	3
1	Wag	Dog	2
2	Scratch	Cat	1
3	Tweet	Bird	1

Опция 2

Ако искаме само изброените дублиращи се редове, можем да използваме HAVING клауза за връщане само на редове с брой по-голям от 1:

SELECT 
    PetId,
    PetName,
    PetType,
    COUNT(*) AS "Count"
FROM Pets
GROUP BY 
    PetId,
    PetName,
    PetType
HAVING COUNT(*) > 1
ORDER BY COUNT(*) DESC;

Резултат:

PETID	PETNAME	PETTYPE	Count
4	Bark	Dog	3
1	Wag	Dog	2

Опция 3

Друга възможност е да използвате ROW_NUMBER() функция на прозореца:

SELECT 
    PetId,
    PetName,
    PetType,
    ROW_NUMBER() OVER ( 
        PARTITION BY PetId, PetName, PetType 
        ORDER BY PetId, PetName, PetType
        ) AS rn
FROM Pets;

Резултат:

PETID	PETNAME	PETTYPE	RN
1	Wag	Dog	1
1	Wag	Dog	2
2	Scratch	Cat	1
3	Tweet	Bird	1
4	Bark	Dog	1
4	Bark	Dog	2
4	Bark	Dog	3

PARTITION BY клауза разделя резултатния набор, произведен от FROM клауза в дялове, към които се прилага функцията. Когато посочим дялове за резултатния набор, всеки дял кара номерирането да започне отново (т.е. номерирането ще започне от 1 за първия ред във всеки дял).

Опция 4

Можем да използваме горната заявка като общ табличен израз:

WITH cte AS 
    (
        SELECT 
            PetId,
            PetName,
            PetType,
            ROW_NUMBER() OVER ( 
                PARTITION BY PetId, PetName, PetType 
                ORDER BY PetId, PetName, PetType
                ) AS Row_Number
        FROM Pets
    )
SELECT * FROM cte WHERE Row_Number <> 1;

Резултат:

PETID	PETNAME	PETTYPE	ROW_NUMBER
1	Wag	Dog	2
4	Bark	Dog	2
4	Bark	Dog	3

Това връща само излишните редове от съответстващите дубликати. Така че, ако има два еднакви реда, той връща един от тях. Ако има три еднакви реда, той връща два и т.н.

Опция 5

Като се има предвид, че нашата таблица не съдържа колона с първичен ключ, можем да се възползваме от rowid на Oracle псевдоколона:

SELECT * FROM Pets
WHERE EXISTS (
  SELECT 1 FROM Pets p2 
  WHERE Pets.PetName = p2.PetName
  AND Pets.PetType = p2.PetType
  AND Pets.rowid > p2.rowid
);

Резултат:

PETID	PETNAME	PETTYPE
1	Wag	Dog
4	Bark	Dog
4	Bark	Dog

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

Едно от предимствата на горния пример е, че можем да заменим SELECT * с DELETE за да премахнете измамата на масата.

Опция 6

И накрая, ето още една опция, която използва rowid псевдоколона:

SELECT * FROM Pets
WHERE rowid > (
  SELECT MIN(rowid) FROM Pets p2  
  WHERE Pets.PetName = p2.PetName
  AND Pets.PetType = p2.PetType
);

Резултат:

PETID	PETNAME	PETTYPE
1	Wag	Dog
4	Bark	Dog
4	Bark	Dog

Същият резултат като предишния пример.

Както в предишния пример, можем да заменим SELECT * с DELETE за да премахнете дублиращи се редове от таблицата.


  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 Dynamic SQL

  3. Връщане на краткото име на ден от дата в Oracle

  4. Oracle Database 20c Нови функции

  5. WSJDBCConnection не обвива обекти от тип Oracle jdbc Connection