Удаление повторяющихся строк из таблицы в Oracle - PullRequest
126 голосов
/ 09 февраля 2009

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

Как удалить все повторяющиеся строки и оставить только одну из них?

Ответы [ 21 ]

2 голосов
/ 10 февраля 2016

1. решение

delete from emp
    where rowid not in
    (select max(rowid) from emp group by empno);

2. sloution

delete from emp where rowid in
               (
                 select rid from
                  (
                    select rowid rid,
                      row_number() over(partition by empno order by empno) rn
                      from emp
                  )
                where rn > 1
               );

3. решение

delete from emp e1
         where rowid not in
          (select max(rowid) from emp e2
           where e1.empno = e2.empno ); 

4. решение

 delete from emp where rowid in
            (
             select rid from
                (
                  select rowid rid,
                  dense_rank() over(partition by empno order by rowid
                ) rn
             from emp
            )
 where rn > 1
);
2 голосов
/ 10 февраля 2016

5. решение

delete from emp where rowid in 
    (
      select  rid from
       (
         select rowid rid,rank() over (partition by emp_id order by rowid)rn from emp     
       )
     where rn > 1
    );
2 голосов
/ 28 декабря 2015

Использование rowid-

delete from emp
 where rowid not in
 (select max(rowid) from emp group by empno);

Использование самостоятельного соединения-

delete from emp e1
 where rowid not in
 (select max(rowid) from emp e2
 where e1.empno = e2.empno );
2 голосов
/ 31 декабря 2015

Решение 4)

 delete from emp where rowid in
            (
             select rid from
                (
                  select rowid rid,
                  dense_rank() over(partition by empno order by rowid
                ) rn
             from emp
            )
 where rn > 1
);
1 голос
/ 02 ноября 2017

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

DELETE FROM
 YourTable
WHERE
 ROWID IN
    (WITH Duplicates
          AS (SELECT
               ROWID RID, 
               ROW_NUMBER() 
               OVER(
               PARTITION BY First_Name, Last_Name, Birth_Date)
                  AS RN
               SUM(1)
               OVER(
               PARTITION BY First_Name, Last_Name, Birth_Date
               ORDER BY ROWID ROWS BETWEEN UNBOUNDED PRECEDING 
                                       AND UNBOUNDED FOLLOWING)
                   AS CNT
              FROM
               YourTable
              WHERE
               Load_Date IS NULL)
     SELECT
      RID
     FROM
      duplicates
     WHERE
      RN > 1);

Что стоит отметить:

1) Мы проверяем дублирование только в полях в разделе partition.

2) Если у вас есть причина выбрать один дубликат среди других, вы можете использовать предложение order by, чтобы в этой строке было row_number () = 1

3) Вы можете изменить сохраненный дубликат числа, изменив последнее предложение where на «Where RN> N» с N> = 1 (я думал, что N = 0 удалит все строки, имеющие дубликаты, но он просто удалит все строки).

4) Добавлено поле «Сумма раздела» в запросе CTE, в котором каждая строка будет помечена номерами строк в группе. Поэтому для выбора строк с дубликатами, включая первый элемент, используйте «WHERE cnt> 1».

1 голос
/ 14 сентября 2017

Проверьте ниже сценарии -

1

Create table test(id int,sal int); 

2.

    insert into test values(1,100);    
    insert into test values(1,100);    
    insert into test values(2,200);    
    insert into test values(2,200);    
    insert into test values(3,300);    
    insert into test values(3,300);    
    commit;

3.

 select * from test;    

Здесь вы увидите 6 записей.
4. запустить под запросом -

delete from 
   test
where rowid in
 (select rowid from 
   (select 
     rowid,
     row_number()
    over 
     (partition by id order by sal) dup
    from test)
  where dup > 1)
  1. select * from test;

Вы увидите, что дубликаты записей были удалены.
Надеюсь, что это решит ваш запрос. Спасибо :)

1 голос
/ 12 января 2014
DELETE FROM tableName  WHERE ROWID NOT IN (SELECT   MIN (ROWID) FROM table GROUP BY columnname);
1 голос
/ 30 мая 2014

Самый быстрый способ для действительно больших столов

  1. Создать таблицу исключений со структурой ниже: exceptions_table

    ROW_ID ROWID
    OWNER VARCHAR2(30)
    TABLE_NAME VARCHAR2(30)
    CONSTRAINT VARCHAR2(30)
    
  2. Попробуйте создать уникальное ограничение или первичный ключ, который будет нарушен дубликатами. Вы получите сообщение об ошибке, потому что у вас есть дубликаты. Таблица исключений будет содержать rowids для повторяющихся строк.

    alter table add constraint
    unique --or primary key
    (dupfield1,dupfield2) exceptions into exceptions_table;
    
  3. Присоединитесь к вашей таблице с таблицей исключения из таблицы rowid и удалите дубликаты

    delete original_dups where rowid in (select ROW_ID from exceptions_table);
    
  4. Если количество удаляемых строк велико, то создайте новую таблицу (со всеми разрешениями и индексами), которая не будет объединяться с помощью exceptions_table by rowid, переименуйте исходную таблицу в таблицу original_dups и переименуйте new_table_with_no_dups в исходную таблицу

    create table new_table_with_no_dups AS (
        select field1, field2 ........ 
        from original_dups t1
        where not exists ( select null from exceptions_table T2 where t1.rowid = t2.row_id )
    )
    
1 голос
/ 20 мая 2014
delete from dept
where rowid in (
     select rowid
     from dept
     minus
     select max(rowid)
     from dept
     group by DEPTNO, DNAME, LOC
);
0 голосов
/ 26 ноября 2013
create or replace procedure delete_duplicate_enq as
    cursor c1 is
    select *
    from enquiry;
begin
    for z in c1 loop
        delete enquiry
        where enquiry.enquiryno = z.enquiryno
        and rowid > any
        (select rowid
        from enquiry
        where enquiry.enquiryno = z.enquiryno);
    end loop;
 end delete_duplicate_enq;
...