Oracle
 sql >> Base de données >  >> RDS >> Oracle

6 façons de sélectionner des lignes en double dans Oracle

Les exemples suivants renvoient des lignes en double à partir d'une table de base de données Oracle.

Exemple de données

Supposons que nous ayons un tableau avec les données suivantes :

SELECT * FROM Pets;

Résultat :

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

Les deux premières lignes sont des doublons, tout comme les trois dernières lignes. Dans ce cas, les lignes en double contiennent des valeurs en double dans toutes les colonnes, y compris la colonne ID.

Option 1

Nous pouvons utiliser la requête suivante pour voir combien de lignes sont des doublons :

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

Résultat :

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

Nous avons regroupé les lignes par toutes les colonnes et renvoyé le nombre de lignes de chaque groupe. Toute ligne dont le nombre est supérieur à 1 est un doublon.

Nous pouvons le classer par nombre dans l'ordre décroissant, de sorte que les lignes avec le plus de doublons apparaissent en premier :

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

Résultat :

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

Option 2

Si nous ne voulons que les lignes en double répertoriées, nous pouvons utiliser le HAVING clause pour renvoyer uniquement les lignes dont le nombre est supérieur à 1 :

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

Résultat :

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

Option 3

Une autre option consiste à utiliser le ROW_NUMBER() fonction fenêtre :

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

Résultat :

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

La PARTITION BY la clause divise le jeu de résultats produit par le FROM clause en partitions auxquelles la fonction est appliquée. Lorsque nous spécifions des partitions pour le jeu de résultats, chaque partition fait recommencer la numérotation (c'est-à-dire que la numérotation commencera à 1 pour la première ligne de chaque partition).

Option 4

Nous pouvons utiliser la requête ci-dessus comme expression de table commune :

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;

Résultat :

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

Cela renvoie uniquement les lignes en excès des doublons correspondants. Donc s'il y a deux lignes identiques, il renvoie l'une d'entre elles. S'il y a trois lignes identiques, il en renvoie deux, et ainsi de suite.

Option 5

Étant donné que notre table ne contient pas de colonne de clé primaire, nous pouvons tirer parti du rowid d'Oracle pseudo-colonne :

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

Résultat :

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

La façon dont cela fonctionne est que chaque ligne d'une base de données Oracle a un rowid pseudo-colonne qui renvoie l'adresse de la ligne. Le rowid est un identifiant unique pour les lignes de la table, et généralement sa valeur identifie de manière unique une ligne dans la base de données. Cependant, il est important de noter que les lignes de différentes tables qui sont stockées ensemble dans le même cluster peuvent avoir le même rowid .

L'un des avantages de l'exemple ci-dessus est que nous pouvons remplacer SELECT * avec DELETE afin de dédupliquer la table.

Option 6

Et enfin, voici une autre option qui utilise le rowid pseudocolonne :

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

Résultat :

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

Même résultat que l'exemple précédent.

Comme pour l'exemple précédent, nous pouvons remplacer SELECT * avec DELETE afin de supprimer les lignes en double de la table.