web-dev-qa-db-ja.com

sqliteデータベースから重複行を削除する

SQLite3には3600万行という巨大なテーブルがあります。

この非常に大きなテーブルには、2つの列があります

  • ハッシュ-テキスト
  • d-実数

ただし、行の一部は重複しています。つまり、hashとdは同じ値を持ちます。

また、2つのハッシュが同一である場合、dの値も同じですが、2つの同一のdsは2つの同一のハッシュを意味しません

とにかく、重複した行を削除します。主キー列がありません。これを行う最速の方法は何ですか?


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

トリックを行うように見えます。

85
Patches

行を区別する方法が必要です。コメントに基づいて、特別な rowid column を使用できます。

(hash,d)ごとに最小のrowidを維持して重複を削除するには:

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

最も高速なのは、まさにそのデータベースを使用することだと思います:同じ列で新しいテーブルを追加しますが、適切な制約(ハッシュ/実際のペアの一意のインデックス?)を使用して、元のテーブルを反復処理し、新しいテーブル、制約違反エラーを無視します(つまり、例外が発生したときに反復を続けます)。

次に、古いテーブルを削除し、新しいテーブルの名前を古いテーブルに変更します。

5
MaDa

主キーの追加がオプションではない場合、1つの方法は、重複したDISTINCTを一時テーブルに保存し、既存のテーブルから重複したレコードをすべて削除してから、一時テーブルから元のテーブルにレコードを追加し直すことです。 。

たとえば(SQL Server 2008向けに記述されていますが、その手法はどのデータベースでも同じです):

_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
_

SqliteにROW_NUMBER()型関数があるかどうかはわかりませんが、もしあれば、ここにリストされているアプローチのいくつかを試すこともできます: SQLテーブルから重複レコードを削除します主キーなし

1
rsbarro