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

74

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

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

  • hash - текст
  • d - real

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

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

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


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

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

Теги:
database
sqlite3

3 ответа

96
Лучший ответ

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

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

delete   from YourTable
where    rowid not in
         (
         select  min(rowid)
         from    YourTable
         group by
                 hash
         ,       d
         )
  • 0
    SQLite не позволяет вам добавить столбец первичного ключа, не так ли?
  • 0
    sqlite> alter table dist add id integer primary key autoincrement; Error: Cannot add a PRIMARY KEY column
Показать ещё 4 комментария
4

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

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

  • 0
    Полагаю, не так элегантно, как просто изменить таблицу, НО одна хорошая вещь в вашем подходе состоит в том, что вы можете запускать его столько раз, сколько захотите, не трогая / не уничтожая исходные данные, пока вы не будете полностью удовлетворены результатами. ,
1

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

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

  • 0
    +1, не уверен, что sqlite поддерживает delete <alias> from <table> <alias> хотя

Ещё вопросы

Сообщество Overcoder
Наверх
Меню