Запрос, который мы использовали для удаления дубликатов в SQL Server
WITH CTE AS(
SELECT name, ROW_NUMBER() OVER(PARTITION BY name ORDERBY name) rnk
FROM T
)
DELETEFROM CTE
WHERE rnk > 1;
в PostgreSQL завершится ошибкой:
ОШИБКА: отношение "cte" не существует
Эта ошибка означает, что мы можем удалять строки из базовых таблиц, но не из CTE. Тем не менее, возможно выполнить удаление дубликатов одним запросом, используя CTE.
Поступим следующим образом:
Удалим все строки из базовой таблицы, возвращая их в табличное выражение (первое CTE).
Используя результат 1 шага, формируем уникальные строки, которые должны остаться в таблице (второе CTE).
Вставляем строки, полученные на шаге 2 в базовую таблицу.
Воспользуемся таблицей из цитируемого примера, чтобы написать запрос:
CREATETABLE T (name varchar(10));
INSERTINTO T VALUES
('John'),
('Smith'),
('John'),
('Smith'),
('Smith'),
('Tom');
Вот и сам запрос
WITH t_deleted AS
(DELETEFROM T returning *), -- 1 шаг
t_inserted AS
(SELECT name, ROW_NUMBER() OVER(PARTITION BY name ORDERBY name) rnk
FROM t_deleted)-- 2 шаг
INSERTINTO T SELECT name FROM t_inserted
WHERE rnk=1; -- 3 шаг (сюда мы перенесли условие отбора из 2 шага для сокращения кода)