Удаление повторяющихся строк из базы данных SQLite
У меня есть огромная таблица-36 миллионов строк-в SQLite3.
в этой очень большой таблице есть два столбца
- хэш - текст
- Д - Реал
однако, некоторые строки дублируются. То есть и хэш, и d имеют одинаковые значения.
кроме того, если два хэша идентичны, то и значения d, но два одинаковых ds не подразумевают двух одинаковых хэшей
в любом случае, я хочу, чтобы удалить дубликаты строки. У меня нет столбца первичного ключа. Какой самый быстрый способ сделать это?
изменить: delete from dist where rowid not in (select max(rowid) from dist group by hash);
Кажется, делает трюк.
3 ответов
вам нужен способ различать строки. Основываясь на вашем комментарии, Вы можете использовать специальный идентификатор rowid колонки для этого.
чтобы удалить дубликаты, сохраняя самый низкий rowid
per (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 без первичного ключа