Ответ 1
DELETE FROM dupes a
WHERE a.ctid <> (SELECT min(b.ctid)
FROM dupes b
WHERE a.key = b.key);
У меня есть таблица в базе данных PostgreSQL 8.3.8, у которой нет ключей/ограничений на нее и имеет несколько строк с точно такими же значениями.
Я хотел бы удалить все дубликаты и сохранить только 1 копию каждой строки.
В частности, имеется один столбец (с именем "ключ" ), который может использоваться для идентификации дубликатов (т.е. должна существовать только одна запись для каждого отдельного "ключа" ).
Как я могу это сделать? (в идеале с одной командой SQL) Скорость не является проблемой в этом случае (всего несколько строк).
DELETE FROM dupes a
WHERE a.ctid <> (SELECT min(b.ctid)
FROM dupes b
WHERE a.key = b.key);
Более быстрое решение
DELETE FROM dups a USING (
SELECT MIN(ctid) as ctid, key
FROM dups
GROUP BY key HAVING COUNT(*) > 1
) b
WHERE a.key = b.key
AND a.ctid <> b.ctid
Это быстро и лаконично:
DELETE FROM dupes T1
USING dupes T2
WHERE T1.ctid < T2.ctid -- delete the older versions
AND T1.key = T2.key; -- add more columns if needed
См. также мой ответ на Как удалить повторяющиеся строки без уникального идентификатора, который содержит дополнительную информацию.
Я пробовал это:
DELETE FROM tablename
WHERE id IN (SELECT id
FROM (SELECT id,
ROW_NUMBER() OVER (partition BY column1, column2, column3 ORDER BY id) AS rnum
FROM tablename) t
WHERE t.rnum > 1);
предоставленный Wikipedia Postgres:
Мне пришлось создать свою собственную версию. Версия, написанная @a_horse_with_no_name, слишком медленная на моей таблице (строки 21M). И @rapimo просто не удаляет дубликаты.
Вот что я использую в PostgreSQL 9.5
DELETE FROM your_table
WHERE ctid IN (
SELECT unnest(array_remove(all_ctids, actid))
FROM (
SELECT
min(b.ctid) AS actid,
array_agg(ctid) AS all_ctids
FROM your_table b
GROUP BY key1, key2, key3, key4
HAVING count(*) > 1) c);
Я бы использовал временную таблицу:
create table tab_temp as
select distinct f1, f2, f3, fn
from tab;
Затем удалите tab
и переименуйте tab_temp
в tab
.
Это сработало для меня. У меня была таблица, термины, содержащие повторяющиеся значения. Выполните запрос, чтобы заполнить временную таблицу всеми повторяющимися строками. Затем я запустил инструкцию delete с этими идентификаторами в таблице temp. Значение - это столбец, содержащий дубликаты.
CREATE TEMP TABLE dupids AS
select id from (
select value, id, row_number()
over (partition by value order by value)
as rownum from terms
) tmp
where rownum >= 2;
delete from [table] where id in (select id from dupids)
РАБОТАЕТ ДЛЯ ВСЕХ ВАРИАНТОВ/ЦВЕТОВ SQL (ТАКЖЕ РАБОТАЕТ В AWS REDSHIFT [POSTGRESQL])
1. Лучший метод для удаления дубликатов → с использованием CTE
WITH DUPLICATE_CTE AS
( SELECT KEY,COUNT(1) AS RANKED FROM <SCHEMANAME>.<TABLENAME>
GROUP BY KEY )
DELETE FROM DUPLICATE_CTE WHERE RANKED > 1
2. Простой метод → Использование функции row_number()/rank, dens_rank()
DELETE FROM <TABLE_ALIAS>
FROM (
SELECT <COLUMN_NAMES>,
ROW_NUMBER() OVER (PARTITION BY KEY) AS RANKED
FROM <SCHEMANAME>.<TABLENAME>
) <TABLE_ALIAS>
WHERE <TABLE_ALIAS>.RANKED >1
Это может оказаться дороже, чем использовать выше
3.Lay-Mans (он же LAME: p) метод (самый общий метод для удаления Perfect Duplicates)
DROP TABLE IF EXISTS backupOfTheTableContainingDuplicates;
CREATE TABLE aNewEmptyTemporaryOrBackupTable
AS SELECT DISTINCT * FROM originalTableContainingDuplicates;
TRUNCATE TABLE originalTableContainingDuplicates;
INSERT INTO originalTableContainingDuplicates SELECT * FROM
aNewEmptyTemporaryOrBackupTable ;
DROP TABLE aNewEmptyTemporaryOrBackupTable ;
ОБЪЯСНЕНИЕ ВЫШЕГО СКРИПТА SQL
Так,
Первый запрос гарантирует, что если у вас есть какая-либо резервная/временная таблица исходной таблицы, содержащая дубликаты, то сначала удалите эту таблицу.
Во втором запросе создается новая таблица (временная/резервная) с уникальными записями в исходной таблице, содержащей дубликаты, поэтому новая временная таблица совпадает с исходной таблицей МИНУС дублирующих записей.
3-й запрос усекает или очищает исходную таблицу.
4-й запрос вставляет или копирует все уникальные записи во временной таблице в исходную таблицу, которая была недавно усечена (поэтому не имеет данных). После выполнения этого запроса исходная таблица будет заполнена уникальными данными, которые были во временной таблице.
5-й запрос, удаляет/удаляет ненужную временную таблицу.
Таким образом, конечный результат состоит в том, что исходная таблица имеет только УНИКАЛЬНЫЕ ЗАПИСИ и не имеет дубликатов.