Pregunta

Estoy probando algo en Oracle y llenado una mesa con algunos datos de la muestra, pero en el proceso que accidentalmente cargado registros duplicados, por lo que ahora no puedo crear una clave primaria utilizando algunas de las columnas.

¿Cómo puedo eliminar todas las filas duplicadas y dejar sólo uno de ellos?

¿Fue útil?

Solución

Utilice la pseudocolumna rowid.

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

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

Otros consejos

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

(fija el paréntesis que falta)

DevX.com :

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

Cuando column1, columna2, etc., es la clave que desea utilizar.

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

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

crear la tabla t2 como seleccionar * distinta de t1;

Usted debe hacer un pequeño bloque PL / SQL utilizando un cursor de bucle 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;

Para seleccionar los duplicados sólo el formato de la consulta puede ser:

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

Así que la pregunta 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 se mantendrá el registro más antiguo en la base de datos para los criterios elegidos en el WHERE CLAUSE.

Oracle Certified Associate (2008)

El uso de rowid -

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

El uso de auto unirse a -

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 se puede eliminar registros duplicados de otro modo

DELETE from table_name a where rowid > (select min(rowid) FROM table_name b where a.column=b.column);
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
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 los realmente grandes tablas

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

    ROW_ID ROWID
    OWNER VARCHAR2(30)
    TABLE_NAME VARCHAR2(30)
    CONSTRAINT VARCHAR2(30)
    
  2. Trate de crear una restricción única o una clave principal que será violado por los duplicados. Usted 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. unirse a su mesa con exceptions_table por rowid y eliminar dups

    delete original_dups where rowid in (select ROW_ID from exceptions_table);
    
  4. Si la cantidad de filas para borrar es grande, a continuación, crear una nueva tabla (con todas las subvenciones e índices) anti-unión con exceptions_table por rowid y cambiar el nombre de la tabla original en la tabla original_dups y renombrar new_table_with_no_dups en 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 )
    )
    

Comprobar continuación guiones -

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;    

Usted verá aquí 6-registros.
4.run debajo 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;

Usted verá que los registros duplicados se han eliminado.
Espero que esto resuelve la consulta. Gracias :)

No he visto ninguna respuesta que utilizan expresiones de tabla comunes y funciones de la ventana. Esto es lo que me parece más fácil de 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);

Algunas cosas para tomar nota:

1) nos limitaremos a comprobar para la duplicación de los campos en la cláusula de partición.

2) Si tiene alguna razón para escoger un duplicado sobre los demás puede utilizar una cláusula ORDER BY para hacer esa fila tendrá row_number () = 1

3) Se puede cambiar el duplicado el número conservado cambiando el final donde cláusula para "¿Dónde RN> N" con N> = 1 (que estaba pensando N = 0 sería eliminar todas las filas que tienen duplicados, pero sería simplemente borrar todas las filas).

4) Se ha añadido el campo de partición Suma la consulta de CTE que etiquetar cada fila con las filas de números en el grupo. Así que para seleccionar filas con duplicados, incluyendo el primer uso elemento "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í:
(Véase el 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
);

solución:

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
);
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top