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

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

Les requêtes suivantes peuvent être utilisées pour renvoyer des lignes en double dans SQLite.

Ici, les lignes en double contiennent des valeurs en double dans toutes les colonnes, y compris la colonne ID.

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. En effet, les trois colonnes contiennent les mêmes valeurs dans chaque ligne en double.

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 

Ici, nous avons regroupé les lignes par toutes les colonnes et renvoyé le nombre de lignes de chaque groupe. Cela nous indique si une ligne est unique (avec un nombre de 1) ou un doublon (avec un nombre supérieur à 1).

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

Résultat :

PetId PetName PetType Count----- ------- ------- -----1 Wag Dog 2 4 Bark Dog 3 

Option 3

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

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

Résultat :

PetId PetName PetType Row_Number----- ------- ------- ----------1 Wag Dog 1 1 Wag Dog 2 2 Scratch Cat 1 3 Tweet Oiseau 1 4 Chien qui aboie 1 4 Chien qui aboie 2 4 Chien qui aboie 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 
            *, 
            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.

Cette requête peut être utile pour afficher le nombre de lignes qui seront supprimées de la table lors d'une opération de déduplication. Dans certains autres SGBD (au moins dans SQL Server), nous pouvons remplacer le dernier SELECT * avec DELETE pour supprimer les lignes en double de la table. Mais SQLite ne nous laissera pas mettre à jour le CTE comme ça.

Heureusement, les deux options suivantes peuvent être modifiées pour effectuer une suppression.

Option 5

Nous pouvons tirer parti du rowid de SQLite :

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 Chien qui bouge 4 Chien qui aboie 4 Chien qui aboie 

Comment cela marche-t-il? 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. Cela peut être supprimé si nécessaire, mais à moins qu'il n'ait été explicitement supprimé, vous pourrez l'exploiter dans vos requêtes.

Option 6

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

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 Chien qui bouge 4 Chien qui aboie 4 Chien qui aboie