web-dev-qa-db-fra.com

Suppression de lignes en double de la base de données sqlite

J'ai une énorme table - 36 millions de lignes - dans SQLite3.

Dans ce très grand tableau, il y a deux colonnes

  • hachage - texte
  • d - réel

Cependant, certaines des lignes sont des doublons. Autrement dit, les hachages et d ont les mêmes valeurs.

De plus, si deux hachages sont identiques, les valeurs de d le sont aussi, mais deux ds identiques n'impliquent pas deux hachages identiques

Quoi qu'il en soit, je veux supprimer les lignes en double. Je n'ai pas de colonne de clé primaire. Quelle est la manière la plus rapide de procéder?


MODIFIER: delete from dist where rowid not in (select max(rowid) from dist group by hash);

Semble faire l'affaire.

85
Patches

Vous avez besoin d'un moyen de distinguer les lignes. Sur la base de votre commentaire, vous pouvez utiliser la spéciale colonne rowid pour cela.

Pour supprimer les doublons en conservant le plus bas rowid par (hash,d):

delete   from YourTable
where    rowid not in
         (
         select  min(rowid)
         from    YourTable
         group by
                 hash
         ,       d
         )
108
Andomar

Je suppose que le plus rapide serait d'utiliser la base de données même: ajoutez une nouvelle table avec les mêmes colonnes, mais avec les contraintes appropriées (un index unique sur le hachage/la paire réelle?), Parcourez la table d'origine et essayez d'insérer des enregistrements dans la nouvelle table, en ignorant les erreurs de violation de contrainte (c'est-à-dire continuer l'itération lorsque des exceptions sont levées).

Supprimez ensuite l'ancienne table et renommez la nouvelle en ancienne.

5
MaDa

Si l'ajout d'une clé primaire n'est pas une option, alors une approche consisterait à stocker les doublons DISTINCT dans une table temporaire, supprimer tous les enregistrements dupliqués de la table existante, puis ajouter les enregistrements dans la table d'origine à partir de la table temporaire .

Par exemple (écrit pour SQL Server 2008, mais la technique est la même pour n'importe quelle base de données):

DECLARE @original AS TABLE([hash] varchar(20), [d] float)
INSERT INTO @original VALUES('A', 1)
INSERT INTO @original VALUES('A', 2)
INSERT INTO @original VALUES('A', 1)
INSERT INTO @original VALUES('B', 1)
INSERT INTO @original VALUES('C', 1)
INSERT INTO @original VALUES('C', 1)

DECLARE @temp AS TABLE([hash] varchar(20), [d] float)
INSERT INTO @temp
SELECT [hash], [d] FROM @original 
GROUP BY [hash], [d]
HAVING COUNT(*) > 1

DELETE O
FROM @original O
JOIN @temp T ON T.[hash] = O.[hash] AND T.[d] = O.[d]

INSERT INTO @original
SELECT [hash], [d] FROM @temp

SELECT * FROM @original

Je ne sais pas si sqlite a une fonction de type ROW_NUMBER(), mais si c'est le cas, vous pouvez également essayer certaines des approches répertoriées ici: Supprimer les enregistrements en double d'une table SQL sans clé primaire

1
rsbarro