Oracle で何かをテストしていて、テーブルにサンプル データを入力しましたが、その過程で誤って重複したレコードを読み込んだため、一部の列を使用して主キーを作成できません。
重複する行をすべて削除し、そのうちの 1 つだけを残すにはどうすればよいですか?
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)
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 );
create table t2 as select distinct * from 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;
本当に大きなテーブルの最速の方法
以下の構造を持つ例外テーブルを作成します: exceptions_table
ROW_ID ROWID
OWNER VARCHAR2(30)
TABLE_NAME VARCHAR2(30)
CONSTRAINT VARCHAR2(30)
重複によって違反される一意の制約または主キーを作成してみてください。重複しているため、エラー メッセージが表示されます。例外表には、重複行の行 ID が含まれます。
alter table add constraint
unique --or primary key
(dupfield1,dupfield2) exceptions into exceptions_table;
テーブルを行 ID で exceptions_table に結合し、dup を削除します
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 )
)
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
);
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
);
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);
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 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 dept
where rowid in (
select rowid
from dept
minus
select max(rowid)
from dept
group by DEPTNO, DNAME, LOC
);
一般的なテーブル式とウィンドウ関数を使用する回答は見当たりませんでした。これは私が最も扱いやすいと思うものです。
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」を使用します。
以下のスクリプトを確認してください -
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;
重複したレコードが削除されていることがわかります。
これでクエリが解決することを願っています。ありがとう :)
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;