programing

Oracle 테이블에서 중복 행 제거

mbctv 2023. 3. 22. 21:59
반응형

Oracle 테이블에서 중복 행 제거

Oracle에서 테스트하고 샘플 데이터를 테이블에 입력했는데, 이 과정에서 실수로 중복 레코드를 로드했기 때문에 일부 열을 사용하여 기본 키를 생성할 수 없습니다.

중복된 행을 모두 삭제하고 1개만 남겨두려면 어떻게 해야 합니까?

를 사용합니다.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 ); 

t1에서 구별된 *를 선택하여 테이블 t2를 작성한다.

루프용 커서를 사용하여 작은 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)

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

이 블로그 투고는 일반적인 사례에 매우 도움이 되었습니다.

행이 완전히 중복된 경우(모든 열의 모든 값에 복사본이 있을 수 있음) 사용할 열이 없습니다!그러나 하나를 유지하려면 각 그룹의 각 행에 대해 고유한 식별자가 필요합니다.다행히 Oracle에는 이미 사용할 수 있는 기능이 있습니다.rowid.Oracle의 모든 행에는 행 ID가 있습니다.이건 물리적인 위치추적기예요즉, Oracle이 Disk에 행을 저장하는 위치를 나타냅니다.이것은 각 행마다 고유합니다.따라서 이 값을 사용하여 복사본을 식별하고 제거할 수 있습니다.이를 수행하려면 상관없는 삭제에서 min()을 min(rowid)으로 바꿉니다.

delete films
where  rowid not in (
  select min(rowid)
  from   films
  group  by title, uk_release_date
)

매우 큰 테이블을 위한 가장 빠른 방법

  1. exceptions_table 구조를 가진 예외 테이블을 만듭니다.

    ROW_ID ROWID
    OWNER VARCHAR2(30)
    TABLE_NAME VARCHAR2(30)
    CONSTRAINT VARCHAR2(30)
    
  2. 중복에 의해 위반되는 고유한 제약 조건 또는 기본 키를 만들어 보십시오.중복이 있기 때문에 에러 메세지가 표시됩니다.예외 테이블에는 중복된 행에 대한 행 ID가 포함됩니다.

    alter table add constraint
    unique --or primary key
    (dupfield1,dupfield2) exceptions into exceptions_table;
    
  3. exceptions_table을 사용하여 테이블을 rowid별로 조인하고 dups를 삭제합니다.

    delete original_dups where rowid in (select ROW_ID from exceptions_table);
    
  4. 삭제할 행의 양이 많은 경우 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 );

해결책 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);
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
);

써놨습니다.
) (실행계획 참조)

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;

3.

 select * from test;    

6월 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)
  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) 중복된 것을 다른 것들보다 선택해야 하는 경우, 주문 기준 절을 사용하여 해당 행에 row_number() = 1이 되도록 할 수 있습니다.

3) 마지막 where 구를 N > = 1과 함께 "Where RN > N"으로 변경하여 보존된 중복 수를 변경할 수 있습니다(N = 0이면 중복되는 행이 모두 삭제되지만 모든 행이 삭제됩니다).

4) 그룹 내 각 행에 번호 행을 태그 붙이는 CTE 쿼리의 [Sum partition]필드를 추가했습니다.따라서 첫 번째 항목을 포함하여 중복되는 행을 선택하려면 "WHERE cnt > 1"을 사용합니다.

솔루션:

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
);
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 max(rowid)
          from your_table
         group by column1, column2, column3
        having count(*) > 1
       );

언급URL : https://stackoverflow.com/questions/529098/removing-duplicate-rows-from-table-in-oracle

반응형