Suppression des lignes dupliquées de la base de données sqlite

j'ai une énorme table - 36 millions de lignes - en SQLite3.

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

  • hash - texte
  • d - réel

Cependant, certaines lignes sont des doublons. C'est-à-dire que le hash et le d ont les mêmes valeurs.

aussi, si deux hachures sont identiques, les valeurs de d sont identiques, mais deux ds identiques n'implique pas deux identiques hashes

quoi qu'il en soit, je veux supprimer les lignes dupliquées. Je n'ai pas de colonne de clé primaire. Quelle est la façon la plus rapide de faire ça?


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

Semble faire l'affaire.

80
demandé sur Jaydeep Karena 2011-11-19 03:45:10

3 réponses

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

pour supprimer les doublons en gardant le plus bas rowid par (hash,d) :

delete   from YourTable
where    rowid not in
         (
         select  min(rowid)
         from    YourTable
         group by
                 hash
         ,       d
         )
99
répondu Andomar 2012-09-14 03:05:46

je suppose que le plus rapide serait d'utiliser la base de données même pour elle: ajouter une nouvelle table avec les mêmes colonnes, mais avec des contraintes appropriées (un index unique sur la paire hash/réel?), itérez dans la table originale et essayez d'insérer des enregistrements dans la nouvelle table, en ignorant les erreurs de violation des contraintes (i.e. continuez à itérer lorsque des exceptions sont soulevées).

Puis supprimer l'ancienne table et renommez le nouveau à l'ancien.

5
répondu MaDa 2011-11-19 00:04:44

Si l'ajout d'une clé primaire n'est pas une option, alors une approche serait de stocker les copies DISTINCTES dans une table temporaire, supprimer toutes les copies des enregistrements de la table existante, puis ajouter les enregistrements dans la table d'origine de la table temporaire.

par exemple (écrit pour SQL Server 2008, mais la technique est la même pour toute 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 suis pas sûr si sqlite a une fonction de type ROW_NUMBER() , mais si elle est-ce que vous pouvez également essayer certaines des approches énumérées ici: supprimer les enregistrements en double d'une table SQL sans une clé primaire

1
répondu rsbarro 2017-05-23 12:10:39