Удаление повторяющихся строк из таблицы в Oracle
Я тестирую что-то в Oracle и заполняю таблицу некоторыми образцами данных, но в процессе я случайно загрузил дубликаты записей, поэтому теперь я не могу создать первичный ключ, используя некоторые столбцы.
Как я могу удалить все повторяющиеся строки и оставить только одну из них?
21 ответов:
использовать
rowidпсевдостолбцом.DELETE FROM your_table WHERE rowid not in (SELECT MIN(rowid) FROM your_table GROUP BY column1, column2, column3);здесь
column1,column2иcolumn3составьте идентифицирующий ключ для каждой записи. Вы можете перечислить все свои столбцы.
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);(исправлена отсутствующая скобка)
От DevX.com:
DELETE FROM our_table WHERE rowid not in (SELECT MIN(rowid) FROM our_table GROUP BY column1, column2, column3...) ;где column1, column2 и др. это ключ, который вы хотите использовать.
DELETE FROM tablename a WHERE a.ROWID > ANY (SELECT b.ROWID FROM tablename b WHERE a.fieldname = b.fieldname AND a.fieldname2 = b.fieldname2)
Решение 1)
delete from emp where rowid not in (select max(rowid) from emp group by empno);решение 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 );решение 3)
delete from emp e1 where rowid not in (select max(rowid) from emp e2 where e1.empno = e2.empno );
для выбора дубликатов только формат запроса может быть:
SELECT GroupFunction(column1), GroupFunction(column2),..., COUNT(column1), column1, column2... FROM our_table GROUP BY column1, column2, column3... HAVING COUNT(column1) > 1поэтому правильный запрос в соответствии с другим предложением:
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....)этот запрос будет хранить самую старую запись в базе данных для критериев, выбранных в
WHERE CLAUSE.Oracle Certified Associate (2008)
используя rowid -
delete from emp where rowid not in (select max(rowid) from emp group by empno);С помощью self join -
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 );
1. решение
delete from emp where rowid not in (select max(rowid) from emp group by empno);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 );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 );
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 );
DELETE from table_name where rowid not in (select min(rowid) FROM table_name group by column_name);и вы также можете удалить дубликаты записей другим способом
DELETE from table_name a where rowid > (select min(rowid) FROM table_name b where a.column=b.column);
вы должны сделать небольшой блок pl / sql с помощью курсора для цикла и удалить строки, которые вы не хотите хранить. Например:
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 dept where rowid in ( select rowid from dept minus select max(rowid) from dept group by DEPTNO, DNAME, LOC );
самый быстрый способ для действительно больших таблиц
создать таблицу исключений со структурой ниже: exceptions_table
ROW_ID ROWID OWNER VARCHAR2(30) TABLE_NAME VARCHAR2(30) CONSTRAINT VARCHAR2(30)попробуйте создать уникальное ограничение или первичный ключ, который будет нарушен дубликатами. Вы получите сообщение об ошибке, потому что у вас есть дубликаты. Таблица исключений будет содержать идентификаторы строк для повторяющихся строк.
alter table add constraint unique --or primary key (dupfield1,dupfield2) exceptions into exceptions_table;присоединиться к таблице с exceptions_table по rowid и дублированные файлы удалить
delete original_dups where rowid in (select ROW_ID from exceptions_table);если количество строк для удаления велико, то создайте новую таблицу (со всеми грантами и индексами) анти-соединение с exceptions_table по 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 ) )
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
Проверьте ниже сценарии -
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)
select * from test;вы увидите, что дубликаты записей были удалены.
Надеюсь, это решит ваш запрос. Спасибо :)
Я не видел никаких ответов, которые используют общие табличные выражения и оконные функции. Это то, с чем мне легче всего работать.
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) добавлено поле Sum partition запрос CTE, который будет помечать каждую строку с числом строк в группе. Поэтому для выбора строк с дубликатами, включая первый пункт, используйте "где 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;
для лучшей производительности, вот что я писал :
(см. план выполнения)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 );
Comments