Удаление повторяющихся строк из таблицы в Oracle
-
22-08-2019 - |
Вопрос
Я тестирую что-то в Oracle и заполняю таблицу некоторыми примерами данных, но в процессе случайно загрузил повторяющиеся записи, поэтому теперь я не могу создать первичный ключ, используя некоторые столбцы.
Как удалить все повторяющиеся строки и оставить только одну из них?
Решение
Использовать 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...) ;
Где столбец1, столбец2 и т. д.это ключ, который вы хотите использовать.
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 );
создать таблицу t2 как выбрать отдельную * из t1;
Вам следует создать небольшой блок 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;
Чтобы выбрать дубликаты, можно использовать только формат запроса:
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 (2008 г.)
Использование 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 );
Решение 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);
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
);
Самый быстрый способ для действительно больших таблиц
Создайте таблицу исключений со структурой ниже:таблица_исключений
ROW_ID ROWID OWNER VARCHAR2(30) TABLE_NAME VARCHAR2(30) CONSTRAINT VARCHAR2(30)
Попробуйте создать уникальное ограничение или первичный ключ, который будет нарушен дубликатами.Вы получите сообщение об ошибке, поскольку у вас есть дубликаты.Таблица исключений будет содержать Rowids для дубликатов строк.
alter table add constraint unique --or primary key (dupfield1,dupfield2) exceptions into exceptions_table;
Присоединитесь к своей таблице с помощьюExceptions_table по идентификатору строки и удалите дубликаты.
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 ) )
Проверьте ниже сценарии -
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) Мы проверяем дублирование только полей в разделе раздела.
2) Если у вас есть причина выбирать один дубликат среди других, вы можете использовать предложение order by, чтобы эта строка имела row_number() = 1.
3) Вы можете изменить сохраненный дубликат номера, изменив последнее предложениеwhere на «Где RN > N» с N >= 1 (я думал, что N = 0 удалит все строки, имеющие дубликаты, но это просто удалит все строки) .
4) Добавлено поле раздела суммы в запрос CTE, который будет помечать каждую строку номером строки в группе.Поэтому, чтобы выбрать строки с дубликатами, включая первый элемент, используйте «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;
Для лучшей производительности вот что я написал:
(см. план выполнения)
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
);
решение :
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
);