sql >> Databáze >  >> RDS >> Oracle

6 způsobů, jak vybrat duplicitní řádky v Oracle

Následující příklady vracejí duplicitní řádky z tabulky databáze Oracle.

Ukázková data

Předpokládejme, že máme tabulku s následujícími údaji:

SELECT * FROM Pets;

Výsledek:

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

První dva řádky jsou duplikáty, stejně jako poslední tři řádky. V tomto případě duplicitní řádky obsahují duplicitní hodnoty ve všech sloupcích, včetně sloupce ID.

Možnost 1

Můžeme použít následující dotaz, abychom viděli, kolik řádků je duplicitních:

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

Výsledek:

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

Seskupili jsme řádky podle všech sloupců a vrátili jsme počet řádků každé skupiny. Každý řádek s počtem větším než 1 je duplikát.

Můžeme to seřadit podle počtu v sestupném pořadí, takže řádky s největším počtem duplikátů se zobrazí jako první:

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

Výsledek:

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

Možnost 2

Pokud chceme, aby byly uvedeny pouze duplicitní řádky, můžeme použít HAVING klauzule pro vrácení pouze řádků s počtem větším než 1:

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

Výsledek:

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

Možnost 3

Další možností je použít ROW_NUMBER() funkce okna:

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

Výsledek:

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 klauzule rozděluje sadu výsledků vytvořenou FROM klauzule do oddílů, na které je funkce aplikována. Když určíme oddíly pro sadu výsledků, každý oddíl způsobí, že číslování začne znovu (tj. číslování začne na 1 pro první řádek v každém oddílu).

Možnost 4

Výše uvedený dotaz můžeme použít jako společný tabulkový výraz:

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;

Výsledek:

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

Tím se vrátí pouze přebytečné řádky z odpovídajících duplikátů. Pokud tedy existují dva stejné řádky, vrátí jeden z nich. Pokud existují tři stejné řádky, vrátí dva atd.

Možnost 5

Vzhledem k tomu, že naše tabulka neobsahuje sloupec primárního klíče, můžeme využít výhod rowid společnosti Oracle pseudosloupec:

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
);

Výsledek:

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

Funguje to tak, že každý řádek v databázi Oracle má rowid pseudosloupec, který vrací adresu řádku. rowid je jedinečný identifikátor pro řádky v tabulce a obvykle jeho hodnota jednoznačně identifikuje řádek v databázi. Je však důležité si uvědomit, že řádky v různých tabulkách, které jsou uloženy společně ve stejném clusteru, mohou mít stejný rowid .

Jednou z výhod výše uvedeného příkladu je, že můžeme nahradit SELECT * pomocí DELETE za účelem odstranění duplicit v tabulce.

Možnost 6

A nakonec je zde další možnost, která používá rowid pseudokloupec:

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

Výsledek:

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

Stejný výsledek jako v předchozím příkladu.

Stejně jako v předchozím příkladu můžeme nahradit SELECT * pomocí DELETE za účelem odstranění duplicitních řádků z tabulky.


  1. IllegalStateException:databáze již uzavřena (pomocí ViewPager)

  2. Jak načíst soubor XML do databáze pomocí balíčku SSIS?

  3. Smazat duplicitní řádky v MySQL (ignoruje primární klíč)

  4. Funkce NULLIF() v Oracle