Удалить дублирующиеся строки, сохранив первую строку
Как удалить дублирующие строки, если уникальный идентификатор строки отсутствует?
У меня есть таблица, которая выглядит следующим образом:
col1 col2 col3 col4 col5 col6 col7
john 1 1 1 1 1 1
john 1 1 1 1 1 1
sally 2 2 2 2 2 2
sally 2 2 2 2 2 2
Я хочу, чтобы после удаления дубликатов у меня остались только следующие строки:
john 1 1 1 1 1 1
sally 2 2 2 2 2 2
Я пробовал несколько запросов, но, похоже, они зависят от наличия идентификатора строки, так как я не получаю желаемого результата. Например, я пытался выполнить следующий запрос:
DELETE
FROM table
WHERE col1 IN (
SELECT id
FROM table
GROUP BY id
HAVING (COUNT(col1) > 1)
)
Не могли бы вы помочь мне решить эту проблему и предоставить запрос, который удаляет дублирующие строки без наличия уникального идентификатора?
5 ответ(ов)
Я также люблю использовать CTE и ROW_NUMBER, так как их сочетание позволяет увидеть, какие строки были удалены (или обновлены). Для этого просто замените DELETE FROM CTE... на SELECT * FROM CTE:
WITH CTE AS(
SELECT [col1], [col2], [col3], [col4], [col5], [col6], [col7],
RN = ROW_NUMBER() OVER (PARTITION BY col1 ORDER BY col1)
FROM dbo.Table1
)
DELETE FROM CTE WHERE RN > 1
При этом результат может отличаться, и я предполагаю, что это связано с опечаткой с вашей стороны.
COL1 COL2 COL3 COL4 COL5 COL6 COL7
john 1 1 1 1 1 1
sally 2 2 2 2 2 2
В этом примере дубликаты определяются по одному столбцу col1 благодаря конструкции PARTITION BY col1. Если вы хотите учесть несколько столбцов, просто добавьте их в PARTITION BY:
ROW_NUMBER() OVER (PARTITION BY Col1, Col2, ... ORDER BY OrderColumn)
Таким образом, вы сможете точно настроить логику определения дубликатов в зависимости от ваших требований.
Без использования CTE и ROW_NUMBER(), вы сможете удалить дубликаты, применяя GROUP BY вместе с функцией MAX. Вот пример:
DELETE
FROM MyDuplicateTable
WHERE ID NOT IN
(
SELECT MAX(ID)
FROM MyDuplicateTable
GROUP BY DuplicateColumn1, DuplicateColumn2, DuplicateColumn3
)
В этом запросе мы выбираем максимальный ID для каждой группы дубликатов по заданным столбцам DuplicateColumn1, DuplicateColumn2 и DuplicateColumn3. После этого мы удаляем все записи, у которых ID не входит в список максимальных значений, тем самым оставляя только одну запись для каждого набора дубликатов.
Если у вас нет ссылок, таких как внешние ключи, вы можете сделать это. Я часто применяю этот подход при тестировании концепций, когда тестовые данные дублируются.
SELECT DISTINCT [col1], [col2], [col3], [col4], [col5], [col6], [col7]
INTO [newTable]
FROM [oldTable]
Затем перейдите в обозреватель объектов и удалите старую таблицу.
После этого переименуйте новую таблицу в имя старой таблицы.
Для удаления всех дубликатов, оставляя только первые (с минимальным значением ID), вы можете использовать следующий SQL-запрос. Этот запрос должен работать не только в вашей СУБД, но и в PostgreSQL:
DELETE FROM table
WHERE id NOT IN (
SELECT MIN(id)
FROM table
GROUP BY col1, col2, col3, col4, col5, col6, col7
);
Данный запрос удаляет все записи, у которых ID не является минимальным для каждой группы, определяемой по столбцам col1, col2, col3, col4, col5, col6, col7. Убедитесь, что вы заменили table на имя вашей таблицы и указали правильные названия столбцов, соответствующие вашему случаю.
Примечание: Перед выполнением команды DELETE всегда рекомендуется сделать резервную копию данных или сначала протестировать запрос с помощью SELECT для проверки, какие строки будут удалены.
Ваш запрос удаляет дубликаты из таблицы search, оставляя только по одной записи для каждого уникального значения url. Давайте разберем его по частям:
Вложенный запрос:
select min(id) from search group by url having count(*) = 1Здесь мы выбираем минимальный
idдля техurl, которые встречаются только один раз в таблице.Объединение с дубликатами:
union SELECT min(id) FROM search group by url having count(*) > 1В этом разделе мы выбираем минимальный
idдляurl, которые имеют более одной записи.Основной запрос:
DELETE from search where id not in (...)Здесь мы находим все записи, чей
idне содержится в результатах вложенного запроса, и удаляем их.
Таким образом, итоговый запрос удалит все дубликаты url, оставив по одной записи с наименьшим id для каждого уникального значения url.
Обратите внимание, что если количество записей для url равно 1, то такая запись останется. Если у вас остались вопросы или нужны уточнения, не стесняйтесь спрашивать!
Как удалить с использованием INNER JOIN в SQL Server?
Как включить и выключить IDENTITY_INSERT в SQL Server 2008?
Обновление и замена части строки
Как удалить несколько строк с разными ID?
Использование таблицы базы данных в качестве очереди