Eliminar filas duplicadas de la tabla en Oracle

Estoy probando algo en Oracle y llené una tabla con algunos datos de muestra, pero en el proceso accidentalmente cargué registros duplicados, por lo que ahora no puedo crear una clave principal usando algunas de las columnas.

¿Cómo puedo eliminar todas las filas duplicadas y dejar solo una?

Use la pseudocolumna rowid .

 DELETE FROM your_table WHERE rowid not in (SELECT MIN(rowid) FROM your_table GROUP BY column1, column2, column3); 

Donde column1 , column2 y column3 constituyen la clave de identificación para cada registro. Puede enumerar todas sus columnas.

De Ask Tom

 delete from t where rowid IN ( select rid from (select rowid rid, row_number() over (partition by companyid, agentid, class , status, terminationdate order by rowid) rn from t) where rn <> 1); 

(solucionado el paréntesis faltante)

De DevX.com :

 DELETE FROM our_table WHERE rowid not in (SELECT MIN(rowid) FROM our_table GROUP BY column1, column2, column3...) ; 

Donde column1, column2, etc. es la clave que desea usar.

 DELETE FROM tablename a WHERE a.ROWID > ANY (SELECT b.ROWID FROM tablename b WHERE a.fieldname = b.fieldname AND a.fieldname2 = b.fieldname2) 

cree la tabla t2 como select distinct * from t1;

Solución 1)

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

Solución 2)

 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 ); 

Solución 3)

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

Para seleccionar los duplicados, solo el formato de consulta puede ser:

 SELECT GroupFunction(column1), GroupFunction(column2),..., COUNT(column1), column1, column2... FROM our_table GROUP BY column1, column2, column3... HAVING COUNT(column1) > 1 

Entonces, la consulta correcta según otra sugerencia es:

 DELETE FROM tablename a WHERE a.ROWID > ANY (SELECT b.ROWID FROM tablename b WHERE a.fieldname = b.fieldname AND a.fieldname2 = b.fieldname2 AND ....so on.. to identify the duplicate rows....) 

Esta consulta mantendrá el registro más antiguo en la base de datos para los criterios elegidos en la WHERE CLAUSE .

Oracle Certified Associate (2008)

Usando rowid-

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

Usando la autocombinación

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

Solución 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. solución

 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.solution

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

4. solución

  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 ); 

5. solución

 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 ); 
 DELETE from table_name where rowid not in (select min(rowid) FROM table_name group by column_name); 

y también puedes eliminar registros duplicados de otra manera

 DELETE from table_name a where rowid > (select min(rowid) FROM table_name b where a.column=b.column); 

Debería hacer un pequeño bloque pl / sql usando un cursor para loop y eliminar las filas que no desea conservar. Por ejemplo:

 declare prev_var my_table.var1%TYPE; begin for t in (select var1 from my_table order by var 1) LOOP -- if previous var equal current var, delete the row, else keep on going. end loop; end; 
 DELETE FROM tableName WHERE ROWID NOT IN (SELECT MIN (ROWID) FROM table GROUP BY columnname); 
 delete from dept where rowid in ( select rowid from dept minus select max(rowid) from dept group by DEPTNO, DNAME, LOC ); 

La forma más rápida para mesas realmente grandes

  1. Crear tabla de excepción con la estructura a continuación: exceptions_table

     ROW_ID ROWID OWNER VARCHAR2(30) TABLE_NAME VARCHAR2(30) CONSTRAINT VARCHAR2(30) 
  2. Intente crear una restricción única o clave principal que será violada por los duplicados. Recibirá un mensaje de error porque tiene duplicados. La tabla de excepciones contendrá los rowids para las filas duplicadas.

     alter table add constraint unique --or primary key (dupfield1,dupfield2) exceptions into exceptions_table; 
  3. Únase a su mesa con exceptions_table por rowid y elimine dups

     delete original_dups where rowid in (select ROW_ID from exceptions_table); 
  4. Si la cantidad de filas para eliminar es grande, cree una nueva tabla (con todas las concesiones e índices) que no coincida con exceptions_table por rowid y renombre la tabla original en la tabla original_dups y cambie el nombre de nueva_tabla_con_no_dups en la tabla original

     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 ) ) 
 create table abcd(id number(10),name varchar2(20)) insert into abcd values(1,'abc') insert into abcd values(2,'pqr') insert into abcd values(3,'xyz') insert into abcd values(1,'abc') insert into abcd values(2,'pqr') insert into abcd values(3,'xyz') select * from abcd id Name 1 abc 2 pqr 3 xyz 1 abc 2 pqr 3 xyz Delete Duplicate record but keep Distinct Record in table DELETE FROM abcd a WHERE ROWID > (SELECT MIN(ROWID) FROM abcd b WHERE b.id=a.id ); run the above query 3 rows delete select * from abcd id Name 1 abc 2 pqr 3 xyz 

Verifique los guiones a continuación –

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; 

Verá aquí 6 registros.
4.run debajo de consulta –

 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;

Verás que se han eliminado los registros duplicados.
Espero que esto resuelva tu consulta. Gracias 🙂

No vi ninguna respuesta que use expresiones comunes de tabla y funciones de ventana. Esto es con lo que me resulta más fácil trabajar.

 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); 

Algo a tener en cuenta:

1) Solo estamos verificando la duplicación en los campos en la cláusula de partición.

2) Si tiene alguna razón para elegir un duplicado sobre otros, puede usar una cláusula order by para que esa fila tenga row_number () = 1

3) Puede cambiar el número duplicado conservado cambiando la cláusula where final a “Where RN> N” con N> = 1 (Estaba pensando que N = 0 eliminaría todas las filas que tienen duplicados, pero simplemente eliminaría todas las filas) .

4) Agregó el campo de partición Sum la consulta CTE que etiquetará cada fila con las filas numéricas en el grupo. Por lo tanto, para seleccionar filas con duplicados, incluido el primer elemento, utilice “WHERE cnt> 1”.

 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; 

Para un mejor rendimiento, esto es lo que escribí:
(ver plan de ejecución)

 DELETE FROM your_table WHERE rowid IN (select t1.rowid from your_table t1 LEFT OUTER JOIN ( SELECT MIN(rowid) as rowid, column1,column2, column3 FROM your_table GROUP BY column1, column2, column3 ) co1 ON (t1.rowid = co1.rowid) WHERE co1.rowid IS NULL );