テーブルの重複行を削除する(Oracle)

今日び、ユニークキー制約が無いテーブルなんてなかなか無いとは思いますが、いちおうメモ。

Oracle限定です。

サンプルとして、こんなテーブル。

(普通は主キー制約あるはずのテーブルですけど。データ型は適当です)

emp
列名データ型
empnonumber(10,0)
empnamechar(30)
jobchar(30)

このテーブルに対して、「emp_no」をユニークキーとする制約を追加したい。

でも、以下のようにemp_noはemp内で重複があります。

emp_no emp_name job
1zettaProgrammer
1zetta1Developer
1zetta2Sales
2HaraAccounting
2Hara(null)
3GeorgeEngineer
4TomEngineer
4Tom2Sales
5Marshall Accounting

データの中身はどうでもいいから、とりあえずユニークキー制約をつけたいって時。

重複行を削除するdelete文はこんな感じに。

delete from emp e1
where
    -- 重複行の条件
    exists (
        select * from emp e2
        where
        e2.emp_no = e1. emp_no
        group by emp_no
        having count(*) > 1)
    -- 重複行グループ内で削除するレコードの条件
    and rowid <> (
        select min(rowid) from emp e3
        group by emp_no
        having count(*) > 1)

一個目のサブクエリが無いと、重複してない行までdeleteされるので注意。

where句のサブクエリ内のwhere句とgroup by句の列指定はユニークキー制約と同じ列項目です。

主クエリwhere句のrowidと比較している所は一意にできればなんでもいいと思います。

もし、残したいデータがあれば、残したいデータの条件を記述してやればいけそうな気がします。(試してません)

エレガントでは無いかもしれませんが、Oracleでは、とりあえずコレでできました。

このエントリーをはてなブックマークに追加
comments powered by Disqus