- ベストアンサー
SQL文の考案願い
いつもお世話になります。 Oracle9で、SQLの作成で躓いております・・・ 厚かましいお願いで恐縮ですが、ご教授頂けないでしょうか? 社員番号、開始日、組織コード、タイムスタンプ・・・(細かい点は省略) とカラムが並んでいるとします。 同じ社員場号のデータは重複なしとしたいのですが、同じ社員番号のデー タが2行出来ているレコードがあり、タイムスタンプで古/新を判断すると いうデータが複数社員分あったとします。 社員一人一行しかないデータはそのままとし、二行できてしまっている 場合、その二行のうち、タイムスタンプが古い物を消して一行とするとい うSQLはどのようになりますでしょうか? よろしくお願いします。 *ちなみに、下記のSQLを投げてカウントが2件となった人を 削除したいと思っています。 select 社員番号, 開始日付, count(社員番号) from TEST where 開始日付 between '2005/12/01' and '2005/12/31' group by 社員番号, 開始日付
- みんなの回答 (3)
- 専門家の回答
質問者が選んだベストアンサー
「社員番号でユニークになる」、「タイムスタンプが古い方を削除」と言いながら、検索で「社員番号+開始日付」でグループ分けしている理由は? OracleでのSQLサポート状況が分からないのですが、次のSQLではどうでしょうか? ●削除される行を確認 select * from TEST where (社員番号,タイムスタンプ) in( select 社員番号,min(タイムスタンプ) from TEST where 開始日付 between '2005/12/01' and '2005/12/31' group by 社員番号 having count(*)>1 ) ●削除 delete from TEST where (社員番号,タイムスタンプ) in( select 社員番号,min(タイムスタンプ) from TEST where 開始日付 between '2005/12/01' and '2005/12/31' group by 社員番号 having count(*)>1 )
その他の回答 (2)
- k_o_r_o_c_h_a_n
- ベストアンサー率55% (526/942)
まずは、重複するデータのうち、古いモノを消すなら・・ delete TEST x where exists(select 1 from TEST y where x.社員番号=y.社員番号 and x.開始日>y.開始日); で良いかと思います。 でもって、消さずに、古いデータを問い合わせ結果から除外するには、 select * from TEST x where not exists (select 1 from TEST y where x.社員番号=y.社員番号 and x.開始日<y.開始日); で良いと思います。 質問にあるSQL上の開始日範囲条件は、どう取り扱うべきか書かれていないので、 あえてふれていません。
お礼
ご回答ありがとうございました。 データを消すツールに頼っていたので、SQLが苦手になっていました。 existsも盲点でした。普段意識して使う関数が少ないことを思い知らされました。 開始日の範囲は今回は決まっていましたが、毎回変わるので 逐一変えます。 本当にありがとうございました。
補足
chukenkenkouさん、7colorsさん、k_o_r_o_c_h_a_nさん、 ご回答ありがとうございました。 これにて質問を締め切りたいと思います。 全員にポイントを付与したいのですが、良回答と次点までのようですので すみませんが、投稿日時順とさせていただきます。
- 7colors
- ベストアンサー率25% (29/114)
KEY項目って何ですか? これだとちょっと読めない。 違う開始日で社員番号重複が可能って事だろうか。 あと、2件といっているが、2件以上もありえたりしないのだろうか? 単純に整理したいだけなら、 SELECT A.社員番号, A.開始日, A.組織コード, A.タイムスタンプ FROM TABLE A WHERE A.タイムスタンプ = ( SELECT MAX(B.タイムスタンプ) FROM TABLE B WHERE B.社員番号 = A.社員番号 AND B.開始日 = A.開始日) これで最新の一覧が取れるのでこれを別テーブルに退避。 全部消して最新分だけ戻すのでもいいと思うのだけど・・・。
お礼
実は例に示した 社員番号, 開始日付, タイムスタンプ以外にも 沢山のカラムがあったのですが、省略して書いてしまいました。 社員番号、開始日付のほかにもキーはありますが、タイムスタンプは 違いました。 恥ずかしながら、HAVING句を良く知らなかった為、うまく組めませんでした。頂いたSQLをヒントに自分なりに組めました。 データを確認したところ、2件以上はありませんでした。 最終的に下記のSQL(カラム名は偽名)を先輩にチェックいただき、 OKとなりました。 SELECT * を DELETE に変え、削除しました。 select * from TEST where (社員番号, 開始日付) in ( select 社員番号, 開始日付 from TEST where 開始日付 between '2005/12/01' and '2005/12/31' group by 社員番号, 開始日付 having count(*) > 1 ) ご回答、ありがとうございました。
お礼
素早いご回答ありがとうございました。 言葉足らずですみません。社員番号と開始日付が同じデータが 2行あったため、タイムスタンプを見て古いほうを消す、という 想定でした。頂いたSQLを参考に自分なりに書き換え、うまく 削除することができました。大変ありがとうございました。