Удалить дублирующиеся строки, сохранив первую строку
Как удалить дублирующие строки, если уникальный идентификатор строки отсутствует?
У меня есть таблица, которая выглядит следующим образом:
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?
Нахождение дубликатов в таблице SQL
Сброс начального значения идентификатора после удаления записей в SQL Server
Переименование столбца в SQL Server 2008
Обновление и замена части строки