Удаление повторяющихся строк из базы данных SQLite


У меня есть огромная таблица - 36 миллионов строк - в SQLite3.

в этой очень большой таблице есть два столбца

  • хэш - текст
  • Д - Реал

однако, некоторые строки дублируются. То есть и хэш, и d имеют одинаковые значения.

кроме того, если два хэша идентичны, то и значения d, но два одинаковых ds не означают два одинаковых хэша

в любом случае, я хочу, чтобы удалить дубликаты строки. У меня нет столбца первичного ключа. Какой самый быстрый способ сделать это?


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

Кажется, чтобы сделать трюк.

3 80

3 ответа:

вам нужен способ различать строки. Основываясь на вашем комментарии, Вы можете использовать специальный столбец rowid для этого.

чтобы удалить дубликаты, сохраняя самый низкий rowid на (hash,d):

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

Я думаю, что самым быстрым было бы использовать для этого саму базу данных: добавить новую таблицу с теми же столбцами, но с соответствующими ограничениями (уникальный индекс на хэш/реальную пару?), повторите исходную таблицу и попробуйте вставить записи в новую таблицу, игнорируя ошибки нарушения ограничений (т. е. продолжайте итерацию при возникновении исключений).

удалить старую таблицу и переименовать новую в старую.

если добавление первичного ключа не является опцией, то один из подходов будет заключаться в том, чтобы хранить дубликаты различных во временной таблице, удалить все дублированные записи из существующей таблицы, а затем добавить записи обратно в исходную таблицу из временной таблицы.

например (написано для 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 без первичного ключа