Voici onze options pour renvoyer des lignes en double dans Oracle Database lorsque ces lignes ont une clé primaire ou une autre colonne d'identifiant unique et que vous souhaitez l'ignorer.
Exemple de données
Nous utiliserons les données suivantes pour nos exemples :
SELECT * FROM Dogs;
Résultat :
DOGID | PRÉNOM | NOM |
---|---|---|
1 | Aboiement | Smith |
2 | Aboiement | Smith |
3 | Ouaf | Jones |
4 | Ruff | Robinson |
5 | Wag | Johnson |
6 | Wag | Johnson |
7 | Wag | Johnson |
Les deux premières lignes sont des doublons et les trois dernières lignes sont des doublons. Les lignes en double partagent exactement les mêmes valeurs dans toutes les colonnes, à l'exception de leur colonne clé primaire/identifiant unique.
La colonne de clé primaire garantit qu'il n'y a pas de lignes en double, ce qui est une bonne pratique dans les SGBDR, car les clés primaires aident à renforcer l'intégrité des données. Mais le fait que les clés primaires contiennent des valeurs uniques signifie que nous devons ignorer cette colonne lors de la recherche de doublons.
Dans notre tableau ci-dessus, la colonne de clé primaire est un nombre incrémentiel, et sa valeur n'a aucune signification et n'est pas significative. Nous pouvons donc ignorer les données de cette colonne lors de la recherche de doublons.
Option 1
Voici notre première option pour renvoyer les doublons :
SELECT
FirstName,
LastName,
COUNT(*) AS Count
FROM Dogs
GROUP BY FirstName, LastName
ORDER BY Count DESC;
Résultat :
PRÉNOM | NOM | COMPTER |
---|---|---|
Wag | Johnson | 3 |
Aboiement | Smith | 2 |
Ruff | Robinson | 1 |
Ouaf | Jones | 1 |
Ici, nous avons construit notre requête avec le GROUP BY
clause afin que la sortie soit regroupée par les colonnes pertinentes. Nous avons également utilisé le COUNT()
fonction pour renvoyer le nombre de lignes identiques. Et nous l'avons classé par nombre dans l'ordre décroissant afin que les doublons apparaissent en premier.
Le résultat nous indique qu'il y a trois lignes contenant Wag Johnson et deux lignes contenant Bark Smith. Ce sont des doublons (ou des triples dans le cas de Wag Johnson). Les deux autres lignes n'ont pas de doublons.
Option 2
Nous pouvons ajouter le HAVING
clause à notre exemple précédent pour exclure les non-doublons de la sortie :
SELECT
FirstName,
LastName,
COUNT(*) AS Count
FROM Dogs
GROUP BY FirstName, LastName
HAVING COUNT(*) > 1
ORDER BY Count DESC;
Résultat :
PRÉNOM | NOM | COMPTER |
---|---|---|
Wag | Johnson | 3 |
Aboiement | Smith | 2 |
Option 3
Nous pouvons également vérifier les doublons sur les colonnes concaténées. Dans ce cas, nous utilisons le DISTINCT
mot-clé pour obtenir des valeurs distinctes, puis utilisez le COUNT()
fonction pour retourner le compte :
SELECT
DISTINCT FirstName || ' ' || LastName AS DogName,
COUNT(*) AS Count
FROM Dogs
GROUP BY FirstName || ' ' || LastName
ORDER BY Count DESC;
Résultat :
DOGNAME | COMPTER |
---|---|
Wag Johnson | 3 |
Bark Smith | 2 |
Ruff Robinson | 1 |
Woof Jones | 1 |
Option 4
Chaque ligne dans 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 (bien qu'il soit 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
).
Quoi qu'il en soit, nous pouvons construire une requête qui utilise le rowid
si nous voulons :
SELECT * FROM Dogs
WHERE EXISTS (
SELECT 1 FROM Dogs d2
WHERE Dogs.FirstName = d2.FirstName
AND Dogs.LastName = d2.LastName
AND Dogs.rowid > d2.rowid
);
Résultat :
DOGID | PRÉNOM | NOM |
---|---|---|
2 | Aboiement | Smith |
6 | Wag | Johnson |
7 | Wag | Johnson |
On pourrait remplacer le SELECT *
avec DELETE
pour effectuer une opération de déduplication sur la table.
Notez que nous aurions pu utiliser le DogId
colonne (notre clé primaire) au lieu du rowid
si nous voulions. Cela dit, le rowid
peut être utile si vous ne pouvez pas utiliser la colonne de clé primaire pour une raison quelconque, ou si la table n'a pas de clé primaire.
Option 5
Voici une autre requête qui utilise le rowid
:
SELECT * FROM Dogs
WHERE rowid > (
SELECT MIN(rowid) FROM Dogs d2
WHERE Dogs.FirstName = d2.FirstName
AND Dogs.LastName = d2.LastName
);
Résultat :
DOGID | PRÉNOM | NOM |
---|---|---|
2 | Aboiement | Smith |
6 | Wag | Johnson |
7 | Wag | Johnson |
Comme pour l'exemple précédent, nous pourrions remplacer le SELECT *
avec DELETE
pour supprimer les lignes en double.
Option 6
Les deux rowid
les options ci-dessus sont idéales si vous devez ignorer complètement la clé primaire dans votre requête (ou si vous n'avez pas du tout de colonne de clé primaire). Cependant, comme mentionné, il est toujours possible de remplacer rowid
avec la colonne de clé primaire - dans notre cas, le DogId
colonne :
SELECT * FROM Dogs
WHERE EXISTS (
SELECT 1 FROM Dogs d2
WHERE Dogs.FirstName = d2.FirstName
AND Dogs.LastName = d2.LastName
AND Dogs.DogId > d2.DogId
);
Résultat :
DOGID | PRÉNOM | NOM |
---|---|---|
2 | Aboiement | Smith |
6 | Wag | Johnson |
7 | Wag | Johnson |
Option 7
Et voici l'autre requête avec le rowid
remplacé par le DogId
colonne :
SELECT * FROM Dogs
WHERE DogId > (
SELECT MIN(DogId) FROM Dogs d2
WHERE Dogs.FirstName = d2.FirstName
AND Dogs.LastName = d2.LastName
);
Résultat :
DOGID | PRÉNOM | NOM |
---|---|---|
2 | Aboiement | Smith |
6 | Wag | Johnson |
7 | Wag | Johnson |
Option 8
Une autre façon de trouver des doublons consiste à utiliser le ROW_NUMBER()
fonction fenêtre :
SELECT
DogId,
FirstName,
LastName,
ROW_NUMBER() OVER (
PARTITION BY FirstName, LastName
ORDER BY FirstName, LastName
) AS row_num
FROM Dogs;
Résultat :
DOGID | PRÉNOM | NOM | ROW_NUM |
---|---|---|---|
1 | Aboiement | Smith | 1 |
2 | Aboiement | Smith | 2 |
4 | Ruff | Robinson | 1 |
7 | Wag | Johnson | 1 |
5 | Wag | Johnson | 2 |
6 | Wag | Johnson | 3 |
3 | Ouaf | Jones | 1 |
Utilisation de la PARTITION
La clause entraîne l'ajout d'une nouvelle colonne, avec un numéro de ligne qui s'incrémente à chaque fois qu'il y a un doublon, mais se réinitialise à nouveau lorsqu'il y a une ligne unique.
Dans ce cas, nous ne regroupons pas les résultats, ce qui signifie que nous pouvons voir chaque ligne en double, y compris sa colonne d'identifiant unique.
Option 9
Nous pouvons également utiliser l'exemple précédent comme expression de table commune dans une requête plus large :
WITH cte AS
(
SELECT
DogId,
FirstName,
LastName,
ROW_NUMBER() OVER (
PARTITION BY FirstName, LastName
ORDER BY FirstName, LastName
) AS row_num
FROM Dogs
)
SELECT * FROM cte WHERE row_num <> 1;
Résultat :
DOGID | PRÉNOM | NOM | ROW_NUM |
---|---|---|---|
2 | Aboiement | Smith | 2 |
5 | Wag | Johnson | 2 |
6 | Wag | Johnson | 3 |
Cette requête exclut les non-doublons de la sortie et exclut une ligne de chaque doublon de la sortie.
Option 10
Voici une autre façon d'obtenir le même résultat que dans l'exemple précédent :
SELECT * FROM Dogs
WHERE DogId IN (
SELECT DogId FROM Dogs
MINUS SELECT MIN(DogId) FROM Dogs
GROUP BY FirstName, LastName
);
Résultat :
DOGID | PRÉNOM | NOM |
---|---|---|
2 | Aboiement | Smith |
6 | Wag | Johnson |
7 | Wag | Johnson |
Cet exemple utilise le MINUS
d'Oracle qui renvoie uniquement les lignes uniques renvoyées par la première requête mais pas par la seconde.
Le MINUS
l'opérateur est similaire à EXCEPT
opérateur dans d'autres SGBD, tels que SQL Server, MariaDB, PostgreSQL et SQLite.
Option 11
Voici encore une autre option pour sélectionner les doublons dans notre tableau :
SELECT *
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
);
Résultat :
DOGID | PRÉNOM | NOM | CHIEN | PRÉNOM | NOM |
---|---|---|---|---|---|
2 | Aboiement | Smith | 1 | Aboiement | Smith |
7 | Wag | Johnson | 5 | Wag | Johnson |
7 | Wag | Johnson | 6 | Wag | Johnson |