182

Oracle で何かをテストしていて、テーブルにサンプル データを入力しましたが、その過程で誤って重複したレコードを読み込んだため、一部の列を使用して主キーを作成できません。

重複する行をすべて削除し、そのうちの 1 つだけを残すにはどうすればよいですか?

4

24 に答える 24

372

rowid擬似列を使用します。

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

column1column2、およびは、各レコードの識別column3キーを構成します。すべての列をリストすることができます。

于 2009-02-09T17:41:15.110 に答える
18

アスク・トムより

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

(不足している括弧を修正)

于 2011-03-18T06:11:43.427 に答える
16

DevX.comから:

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

column1、column2 などは、使用するキーです。

于 2009-02-09T17:43:52.810 に答える
13
DELETE FROM tablename a
      WHERE a.ROWID > ANY (SELECT b.ROWID
                             FROM tablename b
                            WHERE a.fieldname = b.fieldname
                              AND a.fieldname2 = b.fieldname2)
于 2009-11-09T06:18:36.300 に答える
9

解決策 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 ); 
于 2015-12-31T10:32:44.897 に答える
7

create table t2 as select distinct * from t1;

于 2013-01-11T17:01:33.353 に答える
4

ループのカーソルを使用して小さな 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;
于 2009-02-09T17:44:14.883 に答える
2

本当に大きなテーブルの最速の方法

  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. テーブルを行 ID で exceptions_table に結合し、dup を削除します

    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 )
    )
    
于 2014-05-30T01:07:46.577 に答える
2

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
);
于 2016-02-10T09:29:06.543 に答える
2

解決策 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
);
于 2015-12-31T12:28:26.067 に答える
2
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);
于 2017-01-07T06:34:04.297 に答える
2

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 );
于 2015-12-28T14:12:14.433 に答える
1

最高のパフォーマンスのために、ここに私が書いたものがあります:(
実行計画を参照)

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
);
于 2015-03-11T10:04:24.387 に答える
1
delete from dept
where rowid in (
     select rowid
     from dept
     minus
     select max(rowid)
     from dept
     group by DEPTNO, DNAME, LOC
);
于 2014-05-20T08:49:18.430 に答える
1

一般的なテーブル式とウィンドウ関数を使用する回答は見当たりませんでした。これは私が最も扱いやすいと思うものです。

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) 他の重複よりも 1 つの重複を選択する何らかの理由がある場合は、order by 句を使用して、その行が row_number() = 1 になるようにすることができます。

3) 最後の where 句を "Where RN > N" with N >= 1 に変更することで、保持される重複数を変更できます (N = 0 は重複のあるすべての行を削除すると考えていましたが、すべての行を削除するだけです)。 .

4) グループ内の行数で各行にタグを付ける CTE クエリに Sum パーティション フィールドを追加しました。したがって、最初の項目を含む重複のある行を選択するには、「WHERE cnt > 1」を使用します。

于 2017-11-01T23:35:06.773 に答える
1

以下のスクリプトを確認してください -

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)
  1. select * from test;

重複したレコードが削除されていることがわかります。
これでクエリが解決することを願っています。ありがとう :)

于 2017-09-14T09:13:19.447 に答える
0
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;
于 2013-11-26T09:04:20.413 に答える