Как правильно отредактировать запрос на удаление дубликатов?

Рейтинг: 0Ответов: 2Опубликовано: 21.08.2023

Помогите разобраться, есть следующий SQL-запрос на удаление дубликатов:

DELETE from dbo.table_details
WHERE (table_details."type", table.id) in (
                SELECT table_details."type", table.id, count(*)
                FROM dbo.table
                INNER JOIN dbo.table_details ON table_details.id = table.id,
                group by table_details."type", table.ref_id
                having count(*) > 1);

он удаляет дубликаты в двух столбцах: table_details."type" и table.id, но удаляет как дубликаты так и сами строки (т.е. вообще все, если кратко), как можно исправить запрос, чтобы он удалял только дубликаты

Ответы

▲ 0

Схематично:

DELETE 
FROM table t1
WHERE EXISTS (
    SELECT NULL
    FROM table t2
    WHERE t1.{поля дублирования} = t2.{поля дублирования}
    AND t1.primary_id < t2.primary_id 
    )

Запрос удаляет записи-дубликаты по набору полей {поля дублирования}, используя любое уникальное non-NULL поле (например, автоинкрементный синтетический первичный ключ), оставляя запись с наибольшим значением в этом поле (типа самую "последнюю").

Можно использовать иное уникальное non-NULL поле (например, автоматически заполняемое created_at).

Если нужно оставить "самую первую" - поменять знак сравнения в подзапросе.

▲ 0

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

create table test (id int,type varchar(10),descr varchar(10)
  ,dttm timestamp default now());
insert into test values
 (1,'r1','Rec1-1')
,(1,'r1','Rec1-2')
,(1,'r1','Rec1-3')
,(2,'r1','Rec2-1')
,(3,'r3','Rec3-1')
,(3,'r3','Rec3-2')
;
-- запрос
with d as (
  delete from  test
  where (id,type) in (select id,type
      from test t2
      group by id,type 
      having count(*)>1
     )
returning test.id,test.type,test.descr
)
insert into test
select id,type,min(descr) descr from d group by id,type;

Исходная таблица

id type descr dttm
1 r1 Rec1-1 2023-08-21 11:09:19.651633
1 r1 Rec1-2 2023-08-21 11:09:19.651633
1 r1 Rec1-3 2023-08-21 11:09:19.651633
2 r1 Rec2-1 2023-08-21 11:09:19.651633
3 r3 Rec3-1 2023-08-21 11:09:19.651633
3 r3 Rec3-2 2023-08-21 11:09:19.651633

Результат (INSERT 0 2)

id type descr dttm
1 r1 Rec1-1 2023-08-21 11:09:19.659016
2 r1 Rec2-1 2023-08-21 11:09:19.651633
3 r3 Rec3-1 2023-08-21 11:09:19.659016

Поля Descr и dttm - только для показа действий запроса. Они не обязательны.