Voici sept façons de renvoyer des lignes en double dans PostgreSQL lorsque ces lignes ont une clé primaire ou une autre colonne d'identifiant unique.
Cela signifie que les lignes en double partagent exactement les mêmes valeurs dans toutes les colonnes, à l'exception de leur colonne de clé primaire/ID unique.
Exemple de données
Nous utiliserons les données suivantes pour nos exemples :
SELECT * FROM Dogs;
Résultat :
dogid | firstname | lastname -------+-----------+---------- 1 | Bark | Smith 2 | Bark | Smith 3 | Woof | Jones 4 | Ruff | Robinson 5 | Wag | Johnson 6 | Wag | Johnson 7 | Wag | Johnson
Les deux premières lignes sont des doublons (sauf pour le DogId
colonne, qui est la clé primaire de la table et contient une valeur unique sur toutes les lignes). Les trois dernières lignes sont également des doublons (sauf pour le DogId
colonne).
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 comme les clés primaires empêchent les lignes en double, elles peuvent interférer avec notre capacité à trouver des 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 devons donc ignorer cette ligne si nous voulons trouver des doublons dans les autres colonnes.
Option 1
Nous pouvons utiliser le SQL GROUP BY
clause pour regrouper les colonnes par leurs colonnes significatives, puis utilisez le COUNT()
fonction pour retourner le nombre de lignes identiques :
SELECT
FirstName,
LastName,
COUNT(*) AS Count
FROM Dogs
GROUP BY FirstName, LastName;
Résultat :
firstname | lastname | count -----------+----------+------- Ruff | Robinson | 1 Wag | Johnson | 3 Woof | Jones | 1 Bark | Smith | 2
Ici, nous avons exclu la colonne de clé primaire en l'omettant de notre requête.
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 exclure les non-doublons de la sortie avec le HAVING
clause :
SELECT
FirstName,
LastName,
COUNT(*) AS Count
FROM Dogs
GROUP BY FirstName, LastName
HAVING COUNT(*) > 1;
Résultat :
firstname | lastname | count -----------+----------+------- Wag | Johnson | 3 Bark | Smith | 2
Option 3
Voici un exemple de vérification des doublons sur les colonnes concaténées. Dans ce cas, nous utilisons le CONCAT()
fonction pour concaténer nos deux colonnes, utilisez le DISTINCT
mot-clé pour obtenir des valeurs distinctes, puis utilisez le COUNT()
fonction pour retourner le compte :
SELECT
DISTINCT CONCAT(FirstName, ' ', LastName) AS DogName,
COUNT(*) AS Count
FROM Dogs
GROUP BY CONCAT(FirstName, ' ', LastName);
Résultat :
dogname | count ---------------+------- Wag Johnson | 3 Ruff Robinson | 1 Woof Jones | 1 Bark Smith | 2
Option 4
Nous pouvons également utiliser le ROW_NUMBER()
fonction fenêtre :
SELECT
*,
ROW_NUMBER() OVER (
PARTITION BY FirstName, LastName
ORDER BY FirstName, LastName
) AS Row_Number
FROM Dogs;
Résultat :
dogid | firstname | lastname | row_number -------+-----------+----------+------------ 1 | Bark | Smith | 1 2 | Bark | Smith | 2 4 | Ruff | Robinson | 1 5 | Wag | Johnson | 1 6 | Wag | Johnson | 2 7 | Wag | Johnson | 3 3 | Woof | 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 5
Nous pouvons également utiliser l'exemple précédent comme expression de table commune dans une requête plus large :
WITH cte AS
(
SELECT
*,
ROW_NUMBER() OVER (
PARTITION BY FirstName, LastName
ORDER BY FirstName, LastName
) AS Row_Number
FROM Dogs
)
SELECT * FROM cte WHERE Row_Number <> 1;
Résultat :
dogid | firstname | lastname | row_number -------+-----------+----------+------------ 2 | Bark | Smith | 2 6 | Wag | Johnson | 2 7 | Wag | Johnson | 3
Cela exclut les non-doublons de la sortie et exclut une ligne de chaque doublon de la sortie. En d'autres termes, il ne montre que les lignes excédentaires des doublons. Ces lignes sont les meilleures candidates pour être supprimées lors d'une opération de déduplication.
Option 6
Voici une manière plus concise d'obtenir le même résultat que dans l'exemple précédent :
SELECT * FROM Dogs
WHERE DogId IN (
SELECT DogId FROM Dogs
EXCEPT SELECT MIN(DogId) FROM Dogs
GROUP BY FirstName, LastName
);
Résultat :
dogid | firstname | lastname -------+-----------+---------- 6 | Wag | Johnson 2 | Bark | Smith 7 | Wag | Johnson
Une différence entre cet exemple et le précédent est que cet exemple ne nécessite pas de générer notre propre numéro de ligne séparé.
Option 7
Voici encore une autre option pour renvoyer des lignes en double dans Postgres :
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 | firstname | lastname | dogid | firstname | lastname -------+-----------+----------+-------+-----------+---------- 2 | Bark | Smith | 1 | Bark | Smith 7 | Wag | Johnson | 5 | Wag | Johnson 7 | Wag | Johnson | 6 | Wag | Johnson