Подтвердить что ты не робот

Удалить повторяющиеся записи в PostgreSQL

У меня есть таблица в базе данных PostgreSQL 8.3.8, у которой нет ключей/ограничений на нее и имеет несколько строк с точно такими же значениями.

Я хотел бы удалить все дубликаты и сохранить только 1 копию каждой строки.

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

Как я могу это сделать? (в идеале с одной командой SQL) Скорость не является проблемой в этом случае (всего несколько строк).

4b9b3361

Ответ 1

DELETE FROM dupes a
WHERE a.ctid <> (SELECT min(b.ctid)
                 FROM   dupes b
                 WHERE  a.key = b.key);

Ответ 2

Более быстрое решение

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

Ответ 4

Я пробовал это:

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:

https://wiki.postgresql.org/wiki/Deleting_duplicates

Ответ 5

Мне пришлось создать свою собственную версию. Версия, написанная @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);

Ответ 6

Я бы использовал временную таблицу:

create table tab_temp as
select distinct f1, f2, f3, fn
  from tab;

Затем удалите tab и переименуйте tab_temp в tab.

Ответ 7

Это сработало для меня. У меня была таблица, термины, содержащие повторяющиеся значения. Выполните запрос, чтобы заполнить временную таблицу всеми повторяющимися строками. Затем я запустил инструкцию 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)

Ответ 8

РАБОТАЕТ ДЛЯ ВСЕХ ВАРИАНТОВ/ЦВЕТОВ 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-й запрос, удаляет/удаляет ненужную временную таблицу.

Таким образом, конечный результат состоит в том, что исходная таблица имеет только УНИКАЛЬНЫЕ ЗАПИСИ и не имеет дубликатов.