• ベストアンサー

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)を残したいという事です。) どのようにして条件を指定すれば良いのかが分かりません。 どなたか、よろしくお願い致します。

質問者が選んだベストアンサー

  • ベストアンサー
回答No.3

考え方としては、顧客名と郵便番号でグルーピングし、その中での最大の受注日付を取得します。その結果と、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の精度は保証できませんが試してみてください。

eflows
質問者

お礼

なんとか無事処理することが出来ました。 ご協力いただいた皆様、お時間割いていただきありがとうございました。素人なもので、一人では前に進めなかった為、本当に感謝です。

eflows
質問者

補足

なるほど。この様に書けば、古い日付分が抽出できるのですね。自分では見当がつけられなかったので、とても助かります。 ただ、当方のデータベースの場合、きれいに全て日付が入っている状態ではありません。NO.2の方のところに書いた通りの状況です。 上記のSQLで古いデータを削除してから、日付重複分と、日付NULL分はdistinctを使って重複を取り除くのが良いでしょうか?

その他の回答 (4)

  • takopon
  • ベストアンサー率69% (27/39)
回答No.5

条件をまとめると、 ・ 顧客名と郵便番号が重複しているレコードだけを   削除したい。 ・ 削除後に重複しているレコードのうち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を実際に実行してみたわけではないので、 精度・パフォーマンス等は保障できませんが。

eflows
質問者

お礼

なんとか無事処理することが出来ました。 ご協力いただいた皆様、お時間割いていただきありがとうございました。素人なもので、一人では前に進めなかった為、本当に感謝です。

  • PAPA0427
  • ベストアンサー率22% (559/2488)
回答No.4

横槍失礼します。#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) で削除対象データが全て取得できると思いますが。

eflows
質問者

お礼

なんとか無事処理することが出来ました。 ご協力いただいた皆様、お時間割いていただきありがとうございました。素人なもので、一人では前に進めなかった為、本当に感謝です。

eflows
質問者

補足

すみません。ご協力いただいて、大変助かります。 私も上記のように考えてはみたのですが、重複していないデータの中にも受注日がNULLのものが存在する為、OR条件で受注日がNULLのデータも抽出すると、重複していないデータまでもひろってしまうのです。 記述不足ですみませんでした。

回答No.2

データを抽出することが目的(画面表示やレポート出力のため)なら #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)のどちらか(どちらでもよい?)を削除するのなら、ちょっと面倒な記述になるような気がします。(まだちゃんと考えてないのですが。)

eflows
質問者

お礼

なんとか無事処理することが出来ました。 ご協力いただいた皆様、お時間割いていただきありがとうございました。素人なもので、一人では前に進めなかった為、本当に感謝です。

eflows
質問者

補足

あぁ、全くその通りなのです。 説明不足で申し訳ありません。 顧客名+郵便番号+受注日付すべて重複しているデータもあるのです。その場合は削除はどちらでも構いません。 上記のような例もあり、NULLもあり、(重複データで、どちらも日付がNULLというパターンもあります)というごちゃごちゃしたデータベースになってしまっています。 残したいデータ以外には削除フラグを立てたいと考えています。

  • PAPA0427
  • ベストアンサー率22% (559/2488)
回答No.1

SELECT 顧客名,郵便番号c,MAX(受注日付) FROM table1 GROUP BY 顧客名,郵便番号; で取れませんか?さらに項目が多い場合は工夫が必要ですが。

関連するQ&A