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.