Sql как удалить дубликаты из таблицы
Перейти к содержимому

Sql как удалить дубликаты из таблицы

  • автор:

Запрос SQL на удаление дубликатов из таблицы по одному полю

@YuraIvanov не лучше получить сразу значение и передать на удаление? копирование будет время занимать ` SELECT name, surname FROM table group by name, surname HAVING (count(CONCAT(name, surname)) > 1); `

25 июл 2016 в 11:35

@SeniorAutomator нельзя производить удаление в таблице, одновременно выбирая из нее значения. Особенности mysql. Эту особенность можно обойти вложенным запросом (как это сделали некоторые другие отвечающие), однако это будет эквивалентно созданию временной таблицы, т.е. то же самое что и в ответе.

25 июл 2016 в 12:38

Какие-то экзотические варианты предлагаются.

Удалить из таблицы дубликаты (строки с одинаковыми значениями поля col) с меньшим id

DELETE t1 FROM t t1 LEFT JOIN t t2 ON t1.col = t2.col AND t1.id < t2.id WHERE t2.id IS NOT NULL;

через подзапрос

DELETE t FROM t LEFT JOIN (SELECT max(id) as id, col FROM t GROUP BY col) t1 USING(id) WHERE t1.id IS NULL;

Кстати, в указанной статье описан и обход ограничения подзапросов на одновременную выборку и изменение данных.

Отслеживать
ответ дан 10 апр 2015 в 12:56
599 4 4 серебряных знака 5 5 бронзовых знаков

здесь предлагают делать так:

ALTER IGNORE TABLE foobar ADD UNIQUE (name, surname) 

но индекс должен влезть в память.

ну и через временную таблицу естественно есть способ. а так-же через group by.

Отслеживать
ответ дан 15 фев 2013 в 18:26
18.1k 20 20 серебряных знаков 42 42 бронзовых знака

Я бы предложил пересоздать полностью таблицу, установив нужные уникальные столбцы. И отправив в ignore те данные, которые будут дублироваться. Это будет гораздо быстрее, если у вас в таблице очень много данных.

Но если вы хотите сделать это запросом, то это будет медленнее, но тоже возможно. На всякий случай, сначала проверьте, что этот запрос выводит только дублирующие строки, а потом замените SELECT * на DELETE tablename

SELECT * FROM tablename INNER JOIN (SELECT Min(id) minid, name, surname FROM tablename GROUP BY name, surname HAVING Count(1) > 1) AS duplicatesTable ON ( duplicatesTable.name = tablename.name AND duplicatesTable.surname = tablename.surname AND duplicatesTable.minid <> tablename.id ) 

Как удалить дубликаты в sql

Удалить дубликаты можно с помощью DISTINCT . Например у нас есть такая выборка:

SELECT first_name FROM users; first_name ------------ Sean Sean Roman Maxwell Russell Mia Mia 
SELECT DISTINCT first_name FROM users; first_name ------------ Sean Roman Maxwell Russell Mia 

Как видите дубликаты были удалены.

Удаление или поиск дубликатов (повторяющихся) записей в таблице

Начнем с того, что важно определить, отличаются записи хоть одним полем или нет. Оператор DELETE и вообще SQL не позволяет из двух одинаковых записей удалить только одну – либо все дубликаты, либо ни одного.

Однако, используя специфический для IB номер записи, это можно сделать. Например:

DELETE FROM XXX T1 WHERE EXISTS
(SELECT * FROM XXX T2 WHERE
(T2.column1 = T1.column1 or (T2.column1 is null and T2.column1 is null)) AND
(T2.column2 = T1.column2 or (T2.column2 is null and T2.column2 is null)) AND
(. ) AND
( T2.RDB$DB_KEY > T1.RDB$DB_KEY ))

В этом случае используется RDB$DB_KEY – физический номер записи IB. Можно оставить как запись с самым большим DB_KEY, так и с самым меньшим (> или < в последнем условии WHERE).

Для поиска имеющих какой-либо одинаковый столбец записей обычно используется запрос, похожий на следующий:

SELECT * FROM TABLE T1
WHERE (SELECT COUNT(*)
FROM TABLE T2
WHERE T1.FIELD = T2.FIELD ) > 1

Однако этот запрос не совсем эффективен. Вместо него выгоднее использовать процедуру, которая будет выполняться намного быстрее:
(Ann Harrison)

for select field
from table
group by field
having count (field) > 1
into :fld
do
begin
for select field
from table
where field = :fld
into :fld1
do
begin
suspend;
end
end

Но хранимая процедура не всегда удобна. Также можно использовать уникальный идентификатор записи RDB$DB_KEY:
(Josef Marie M. Alba)

SELECT * FROM TABLE T1
WHERE EXISTS
(SELECT FIELD FROM TABLE T2
WHERE T1.FIELD = T2.FIELD AND
T1.RDB$DB_KEY != T2.RDB$DB_KEY )

Copyright iBase.ru © 2002-2023

Простой и эффективный метод удаления дубликатов из таблицы

Как быстро и просто удалить дубликаты данных в SQL-базе, чтобы избежать ошибок в программном коде, который использует эти данные.

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

В этой короткой статье я хочу поделиться простым способом удаления дубликатов из таблицы. Запрос работает в базах данных MySQL, MariaDB и PostgreSQL. Если вам интересен такой запрос для других СУБД, напишите мне в комментариях.

Все вышеизложенные а также любые другие запросы можно воспроизвести на SQLize.online – онлайн редакторе SQL.

Давайте начнем. Предположим, у нас есть простая таблица с двумя столбцами: id – это первичный ключ и v простое целочисленное значение

create table tbl ( id int primary key, val int ); insert into tbl (id, val) values (1, 1), (2, 1), (3, 2), (4, 2), (5, 1), (6, 1), (7, 2), (8, 3), (9, 2), (10, 4), (11, 3); 

Приведенный выше код создает таблицу и вставляет несколько значений. Выведем на экран все строки из нашей тестовой таблицы. Как видите, id имеет уникальные значения, но поле val имеет содержит дубликаты:

SELECT * FROM tbl; +====+===+ | id | v | +====+===+ | 1 | 1 | | 2 | 1 | | 3 | 2 | | 4 | 2 | | 5 | 1 | | 6 | 1 | | 7 | 2 | | 8 | 3 | | 9 | 2 | | 10 | 4 | | 11 | 3 | +----+---+ 

Наша задача состоит в том, чтобы удалить строки с поввторяющимися значениями в столбце val и сохранить уникальные значения с минимальным значением идентификатора id.

Для начала попробуем найти дубликаты. Мы можем использовать простое LEFT JOIN таблицы самой с собой по полю val с дополнительным условием для предотвращения объединения идентичных строк (для наглядности дадим алиасы для таблицы и копии):

select * from tbl source_tbl left join tbl copy_tbl on source_tbl.val = copy_tbl.val and source_tbl.id > copy_tbl.id; 

В результате запроса получим следующий результат:

+====+===+========+========+ | id | val | id | val | +====+===+========+========+ | 1 | 1 | (null) | (null) | | 2 | 1 | 1 | 1 | | 3 | 2 | (null) | (null) | | 4 | 2 | 3 | 2 | | 5 | 1 | 1 | 1 | | 5 | 1 | 2 | 1 | | 6 | 1 | 1 | 1 | | 6 | 1 | 2 | 1 | | 6 | 1 | 5 | 1 | | 7 | 2 | 3 | 2 | | 7 | 2 | 4 | 2 | | 8 | 3 | (null) | (null) | | 9 | 2 | 3 | 2 | | 9 | 2 | 4 | 2 | | 9 | 2 | 7 | 2 | | 10 | 4 | (null) | (null) | | 11 | 3 | 8 | 3 | +----+---+--------+--------+ 

Видно, что уникальные строки с минимальным id имеют (null) в столбцах из copy_tbl. Это происходит потому что для минимального значения id в исходной таблице нет строк соответсвующих условию в таблице копии. Итак, нам нужно оставить строки в которых нет соответствия (уникальные) и удалить. Это можно осуществить следующим запросом:

delete tbl.* from tbl left join t copy_tbl on tbl.val = copy_tbl.val and tbl.id > copy_tbl.id where copy_tbl.id is not null; 

P.S. Уже после написания этой статьи мой коллега @Akina предложил более короткую версию:

delete tbl.* from tbl join t copy_tbl on tbl.val = copy_tbl.val and tbl.id > copy_tbl.id; 

Если Вам понравилась статья, Вы можете поддержать автора.

Следите за новыми постами по любимым темам

Подпишитесь на интересующие вас теги, чтобы следить за новыми постами и быть в курсе событий.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *