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

11 façons de trouver des lignes en double tout en ignorant la clé primaire dans SQLite

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 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 lancer une requête avec le GROUP BY clause afin de 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
ORDER BY Count DESC; 

Résultat :

FirstName LastName Count--------- -------- -----Wag Johnson 3 Bark Smith 2 Ruff Robinson 1 Woof Jones 1 

Ici, 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 2 

Option 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 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 :

Compte de nom de chien------------- -----Wag Johnson 3 Bark Smith 2 Woof Jones 1 Ruff Robinson 1 

Option 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 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 FirstName LastName----- --------- --------2 Bark 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 FirstName LastName----- --------- --------2 Bark 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 FirstName LastName----- --------- --------2 Bark Smith 6 Wag Johnson 7 Wag Johnson 

Option 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 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 
            *,
            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.

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 Johnson 

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 FirstName LastName DogId FirstName LastName----- --------- -------- ----- --------- ----- ---2 Bark Smith 1 Bark Smith 7 Wag Johnson 5 Wag Johnson 7 Wag Johnson 6 Wag Johnson