Voici onze options pour renvoyer des lignes en double dans SQLite lorsque ces lignes ont une clé primaire ou une autre colonne d'identifiant unique (mais vous souhaitez ignorer la clé primaire).
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 Robinson5 Wag Johnson 6 Wag Johnson 7 Wag JohnsonLes 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 leDogId
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 lancer une requête avec le
GROUP BY
clause afin de regrouper les colonnes par leurs colonnes significatives, puis utilisez leCOUNT()
fonction pour retourner le nombre de lignes identiques :SELECT FirstName, LastName, COUNT(*) AS Count FROM Dogs GROUP BY FirstName, LastName ORDER BY Count DESC;
Résultat :
FirstName LastName Count--------- -------- -----Wag Johnson 3 Bark Smith 2 Ruff Robinson 1 Woof Jones 1Ici, nous avons exclu la colonne de clé primaire en l'omettant de notre requête. Nous l'avons également 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 utiliser le
HAVING
clause 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 :
FirstName LastName Count--------- -------- -----Wag Johnson 3 Bark Smith 2Option 3
Voici un exemple de vérification des doublons sur les colonnes concaténées. Dans ce cas, nous utilisons le
DISTINCT
mot-clé pour obtenir des valeurs distinctes, puis utilisez leCOUNT()
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 :
Compte de nom de chien------------- -----Wag Johnson 3 Bark Smith 2 Woof Jones 1 Ruff Robinson 1Option 4
Par défaut, chaque ligne dans SQLite a une colonne spéciale, généralement appelée
rowid
, qui identifie de manière unique cette ligne dans le tableau. À moins qu'il n'ait été explicitement supprimé du tableau, vous pouvez l'utiliser comme identifiant unique pour chaque ligne.On peut donc utiliser le
rowid
dans notre requête :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 FirstName LastName----- --------- --------2 Bark Smith 6 Wag Johnson 7 Wag JohnsonOn pourrait remplacer le
SELECT *
avecDELETE
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 durowid
si nous voulions. Cela dit, lerowid
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 FirstName LastName----- --------- --------2 Bark Smith 6 Wag Johnson 7 Wag JohnsonComme pour l'exemple précédent, nous pourrions remplacer le
SELECT *
avecDELETE
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 remplacerrowid
avec la colonne de clé primaire - dans notre cas, leDogId
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 FirstName LastName----- --------- --------2 Bark Smith 6 Wag Johnson 7 Wag JohnsonOption 7
Et voici l'autre requête avec le
rowid
remplacé par leDogId
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 FirstName LastName----- --------- --------2 Bark Smith 6 Wag Johnson 7 Wag JohnsonOption 8
Une autre façon de le faire est d'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 1Utilisation 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 *, 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 3Cela 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 EXCEPT SELECT MIN(DogId) FROM Dogs GROUP BY FirstName, LastName );
Résultat :
DogId FirstName LastName----- --------- --------2 Bark Smith 6 Wag Johnson 7 Wag JohnsonOption 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 FirstName LastName DogId FirstName LastName----- --------- -------- ----- --------- ----- ---2 Bark Smith 1 Bark Smith 7 Wag Johnson 5 Wag Johnson 7 Wag Johnson 6 Wag Johnson