- ベストアンサー
Oracle 重複データの削除の仕方について教えて下さい
お世話になります。 最近データベースを触り始めた初心者です。 色々見たのですが、分からなかった為、教えて下さい。 テーブル名:table1 顧客名 郵便番号 受注日付 customer_nm post_no jutyu_ymd -------------------------------------------- (1) 鈴木一郎 1111111 2004/01/05 (2) 鈴木一郎 1111111 2003/07/01 (3) 佐藤花子 2222222 2002/09/30 (4) 佐藤花子 2222222 NULL 上記のような、顧客テーブルがあったとします。 顧客名と郵便番号が同一だけれど、日付が違う為、重複 データとなってしまっています。 日付の古い方を削除、またNULLの場合は日付のある方を 残したいと考えています。 (つまり、上の場合は(1)と(3)を残したいという事です。) どのようにして条件を指定すれば良いのかが分かりません。 どなたか、よろしくお願い致します。
- みんなの回答 (5)
- 専門家の回答
質問者が選んだベストアンサー
考え方としては、顧客名と郵便番号でグルーピングし、その中での最大の受注日付を取得します。その結果と、table1の受注日付を比較し、一致しなければ削除をすれば可能な気がします。 SELECT T1.* FROM TABLE1 T1,(SELECT CUSTOMER_NM,POST_NO,MAX(JUTYU_YMD) JUTYU_YMD FROM TABLE1 GROUP BY CUSTOMER_NM,POST_NO) T2 WHERE T1.CUSTOMER_NM = T2.CUSTOMER_NM AND T1.POST_NO = T2.POST_NO AND T1.JUTYU_YMD != T2.JUTYU_YMD これで、削除したいデータが検索できませんか?即席でSQLの精度は保証できませんが試してみてください。
その他の回答 (4)
- takopon
- ベストアンサー率69% (27/39)
条件をまとめると、 ・ 顧客名と郵便番号が重複しているレコードだけを 削除したい。 ・ 削除後に重複しているレコードのうち1レコードだけ は必ず残したい。 ・ 残す優先度は、 (1) 日付が最新 (2) 日付がNULLでない という感じてよいのであれば、安直ですが、 まず、 DELETE TABLE1 WHERE (select count(*) from TABLE1 SUB1 where SUB1.顧客名 = TABLE1.顧客名 and SUB1.郵便番号 = TABLE1.郵便番号 ) > 1 AND ( ( TABLE1.受注日付 <> (select MAX(SUB2.受注日付) from TABLE1 SUB2 where SUB2.顧客名 = TABLE1.顧客名 and SUB2.郵便番号 = TABLE1.郵便番号 ) OR ( TABLE1.受注日付 is null ) ) AND (select MAX(SUB3.受注日付) from TABLE1 SUB3 where SUB3.顧客名 = TABLE1.顧客名 and SUB3.郵便番号 = TABLE1.郵便番号 ) is not null を実行します。 これで、顧客名・郵便番号が重複し、 すべてのレコードの受注日付が、同じまたはNULLでない データが消せると思います。 その後さらに、 DELETE TABLE1 WHERE (select count(*) from TABLE1 SUB1 where SUB1.顧客名 = TABLE1.顧客名 and SUB1.郵便番号 = TABLE1.郵便番号 ) > 1 AND ( TABLE1.ROWID <> (select MAX(SUB2.ROWID) from TABLE1 SUB2 where SUB2.顧客名 = TABLE1.顧客名 and SUB2.郵便番号 = TABLE1.郵便番号 ) ) で、残る顧客名・郵便番号・受注日付すべてが重複しているデータを一つだけ残して削除できると思います。 このSQLを実際に実行してみたわけではないので、 精度・パフォーマンス等は保障できませんが。
お礼
なんとか無事処理することが出来ました。 ご協力いただいた皆様、お時間割いていただきありがとうございました。素人なもので、一人では前に進めなかった為、本当に感謝です。
- PAPA0427
- ベストアンサー率22% (559/2488)
横槍失礼します。#1の者です。 #3さんのmomo rightさんのSQLをモデファイすれば出来ますよ。 SELECT T1.* FROM TABLE1 T1,(SELECT CUSTOMER_NM,POST_NO,MAX(JUTYU_YMD) JUTYU_YMD FROM TABLE1 GROUP BY CUSTOMER_NM,POST_NO) T2 WHERE T1.CUSTOMER_NM = T2.CUSTOMER_NM AND T1.POST_NO = T2.POST_NO AND (T1.JUTYU_YMD != T2.JUTYU_YMD OR T2.JUTYU_YMD IS NULL) で削除対象データが全て取得できると思いますが。
お礼
なんとか無事処理することが出来ました。 ご協力いただいた皆様、お時間割いていただきありがとうございました。素人なもので、一人では前に進めなかった為、本当に感謝です。
補足
すみません。ご協力いただいて、大変助かります。 私も上記のように考えてはみたのですが、重複していないデータの中にも受注日がNULLのものが存在する為、OR条件で受注日がNULLのデータも抽出すると、重複していないデータまでもひろってしまうのです。 記述不足ですみませんでした。
- tsukasa-12r
- ベストアンサー率65% (358/549)
データを抽出することが目的(画面表示やレポート出力のため)なら #1 さんの回答が全てだと思うのですが、もしかすると目的は不要データの削除(ディスク・スペースを空けるためや、パフォーマンス改善のためなど?)なのでしょうか? 削除することが目的だとすると、一つお聞きしたいのですが、 顧客名+郵便番号+受注日付の組み合わせは一意になっているのでしょうか?つまり (1) 鈴木一郎 1111111 2004/01/05 (2) 鈴木一郎 1111111 2004/01/05 (3) 鈴木一郎 1111111 2003/07/01 (4) 佐藤花子 2222222 2002/09/30 (5) 佐藤花子 2222222 NULL の(1)、(2)ようなデータはあり得ないのでしょうか? もし、顧客名+郵便番号+受注日付の組み合わせは一意になっていなくて、(1)、(2)のどちらか(どちらでもよい?)を削除するのなら、ちょっと面倒な記述になるような気がします。(まだちゃんと考えてないのですが。)
お礼
なんとか無事処理することが出来ました。 ご協力いただいた皆様、お時間割いていただきありがとうございました。素人なもので、一人では前に進めなかった為、本当に感謝です。
補足
あぁ、全くその通りなのです。 説明不足で申し訳ありません。 顧客名+郵便番号+受注日付すべて重複しているデータもあるのです。その場合は削除はどちらでも構いません。 上記のような例もあり、NULLもあり、(重複データで、どちらも日付がNULLというパターンもあります)というごちゃごちゃしたデータベースになってしまっています。 残したいデータ以外には削除フラグを立てたいと考えています。
- PAPA0427
- ベストアンサー率22% (559/2488)
SELECT 顧客名,郵便番号c,MAX(受注日付) FROM table1 GROUP BY 顧客名,郵便番号; で取れませんか?さらに項目が多い場合は工夫が必要ですが。
お礼
なんとか無事処理することが出来ました。 ご協力いただいた皆様、お時間割いていただきありがとうございました。素人なもので、一人では前に進めなかった為、本当に感謝です。
補足
なるほど。この様に書けば、古い日付分が抽出できるのですね。自分では見当がつけられなかったので、とても助かります。 ただ、当方のデータベースの場合、きれいに全て日付が入っている状態ではありません。NO.2の方のところに書いた通りの状況です。 上記のSQLで古いデータを削除してから、日付重複分と、日付NULL分はdistinctを使って重複を取り除くのが良いでしょうか?