J'ai une énorme table - 36 millions de lignes - dans SQLite3.
Dans ce très grand tableau, il y a deux colonnes
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.
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
)
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.
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