Удаление повторяющихся строк из базы данных sqlite - PullRequest
84 голосов
/ 19 ноября 2011

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

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

  • хэш - текст
  • d - реальный

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

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

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


РЕДАКТИРОВАТЬ: delete from dist where rowid not in (select max(rowid) from dist group by hash);

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

Ответы [ 3 ]

106 голосов
/ 19 ноября 2011

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

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

delete   from YourTable
where    rowid not in
         (
         select  min(rowid)
         from    YourTable
         group by
                 hash
         ,       d
         )
5 голосов
/ 19 ноября 2011

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

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

1 голос
/ 19 ноября 2011

Если добавление первичного ключа не является опцией, то одним из подходов будет сохранение дубликатов 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 без первичного ключа

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...