답변:
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);
(없는 괄호를 수정)
DELETE FROM tablename a
WHERE a.ROWID > ANY (SELECT b.ROWID
FROM tablename b
WHERE a.fieldname = b.fieldname
AND a.fieldname2 = b.fieldname2)
delete from emp
where rowid not in
(select max(rowid) from emp group by empno);
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
);
delete from emp e1
where rowid not in
(select max(rowid) from emp e2
where e1.empno = e2.empno );
t1과 구별되는 선택으로 테이블 t2를 작성하십시오.
distinct *
-1 열에 1 개 이상의 기호가 다른 모든 레코드를 사용합니다. 기본 키를 만들려는 열에서만 고유 한 값을 선택하기 만하면됩니다. Bill의 대답은이 방법의 좋은 예입니다.
커서 for 루프를 사용하여 작은 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 Certified Associate (2008)
정말 큰 테이블을위한 가장 빠른 방법
아래 구조로 예외 테이블을 작성하십시오. exceptions_table
ROW_ID ROWID
OWNER VARCHAR2(30)
TABLE_NAME VARCHAR2(30)
CONSTRAINT VARCHAR2(30)
복제본이 위반하는 고유 제한 조건 또는 기본 키를 작성하십시오. 중복되어 있기 때문에 오류 메시지가 나타납니다. 예외 테이블에는 중복 행의 rowid가 포함됩니다.
alter table add constraint
unique --or primary key
(dupfield1,dupfield2) exceptions into exceptions_table;
rowid로 exceptions_table을 사용하여 테이블을 조인하고 dups를 삭제하십시오.
delete original_dups where rowid in (select ROW_ID from exceptions_table);
삭제할 행의 수가 많은 경우 rowid로 exceptions_table을 사용하여 조인을 방지하고 모든 부여 및 인덱스가있는 새 테이블을 만들고 원래 테이블의 이름을 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 )
)
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 );
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
);
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 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
);
아래 스크립트를 확인하십시오-
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;
삼.
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) N> = 1을 사용하여 final where 절을 "Where RN> N"으로 변경하여 보존되는 숫자 중복을 변경할 수 있습니다 (N = 0은 중복이있는 모든 행을 삭제하지만 모든 행을 삭제한다고 생각했습니다) .
4) Sum 파티션 필드에 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 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
);