- ベストアンサー
Oracleの最新日付との比較で条件を設定する方法
- Oracleで同一商品番号の最新日付を利用した条件を作成する方法について悩んでいます。
- AテーブルとBテーブルの商品番号が同じ場合は除外し、残されたデータからCテーブルの中で最新の日付が当月のデータを残したいです。
- SQLの中でmax関数とシステム日付を使って、最新日付との比較を試みましたが、うまく結果が得られません。ビューを作成する代わりに、一つのSQLクエリで実現する方法を教えていただきたいです。
- みんなの回答 (4)
- 専門家の回答
質問者が選んだベストアンサー
>最新の日付が当月の場合はデータを残す。 >つまり、前月以前のデータは除外となります。 別に最新にこだわる必要はなく(当月のデータが1件でもあれば最新じゃなくても条件成立のため) 補足の Select * from aテーブル a where not exists (select 'X' from bテーブル b where a.商品番号 = b.商品番号) and not exists (select 'X' from cテーブル where (a.商品番号 = c.商品番号) and /* ここから */ (select to_char(to_date(max(c.日付),'YYYYMM'),'YYYYMM') ,'YYYYMM') < to_char(to_date(to_char(sysdate,'YYYYMM'),'YYYYMM')-1 ,'YYYYMM') の /* ここから */以下を、 to_char(to_date(c.日付,'YYYYMM'),'YYYYMM') < to_char(to_date(to_char(sysdate,'YYYYMM'),'YYYYMM')-1,'YYYYMM') ) としても取得できます。但し、負荷が高い、レスポンスが悪いかな。 and a.商品番号 not in (select distinct 商品番号 from cテーブル where trunc(日付,'MM')>=trunc(sysdate,'MM') ) か and not exists (select 'X' from cテーブル where c.商品番号 = a.商品番号 and c.日付 = (select max(c2.日付) from cテーブル c2 where c2.商品番号 = c.商品番号) and trunc(c.日付,'MM')>=trunc(sysdate,'MM') ) あるいは and not exists (select 'X' from cテーブル where c.商品番号 = a.商品番号 and c.日付 = (select max(c2.日付) from cテーブル c2 where c2.商品番号 = c.商品番号 and trunc(c2.日付,'MM')>=trunc(sysdate,'MM') ) か。 どれが早いかは、抽出された結果の商品番号の件数やaテーブルの件数等に依存しますので 良く分かりませんが。
その他の回答 (3)
- yamada_g
- ベストアンサー率68% (258/374)
A,B,Cの3テーブルがあるということですよね? 最終的に取得したい項目が不明ですが、 select a.商品番号, max(c.日付) 最新日付 from ( select a.商品番号 from aテーブル a where not exists ( select * from bテーブル b where a.商品番号 = b.商品番号)) a inner join cテーブル c on (a.商品番号 = c.商品番号) group by a.商品番号 having trunc(max(c.日付) , 'MM') = trunc(sysdate, 'MM'); みたいな感じでどうでしょうか。
お礼
inner joinでの結合はどうもテーブルの関係上 マテリアルビュー等を使用しているため非常に重いのが難点でした。 ありがとうございました。
- bin-chan
- ベストアンサー率33% (1403/4213)
> 1まではできています。 > 上記sqlでビューを作成してといったことは、今回やらずに fromにselect文を書けます。1をfromに書けばSQLは1文。 ただし*で書かずに列を列挙、さらに全体を()で囲む。 select 商品番号, 最新日付 from ( Select a.商品番号, max(c.日付) as 最新日付, from aテーブル where not exists (select 'X' from bテーブル where a.商品番号 = b.商品番号) group by a.商品番号 ) c where <dualから取得した日付とc.最新日付とをごにょごにょする>
お礼
ありがとうございます。 若干改造は必要のようでしたが、参考になりました!
補足
ご回答ありがとうございます。 試してみます。 結果は回答と共にお知らせさせていただきます。
- bin-chan
- ベストアンサー率33% (1403/4213)
> システム日付を年月のみで比較する等試みましたが、 比較部分をどのように記述してますか?日付はDate型じゃなのかな? Date型なら文字列にしてしまうのが簡単かも。 select to_char( sysdate, 'YYYY/MM' ) from dual;
お礼
ありがとうございます。 抽出はなんとかできましたm(_ _)m
補足
目的は、削除リストを作成するためにSQLで削除対象となるデータを 抽出します。 SQLですとAテーブルとBテーブルに一致する場合は削除対象外としています。 Cは履歴のテーブルで同じ商品番号が複数存在します。 そこから一番新しい日付のものを取得したいです。 ブランクのものもあり、ブランクのものは当月のデータと 同一で削除対象外とします。 Select * from aテーブル where not exists (select 'X' from bテーブル where a.商品番号 = b.商品番号) and not exists (select 'X' from cテーブル where (a.商品番号 = c.商品番号) and (select to_char(to_date(max(c.日付),'YYYYMM'),'YYYYMM') ,'YYYYMM') < to_char(to_date(to_char(sysdate,'YYYYMM'),'YYYYMM')-1 ,'YYYYMM') 確か上記だったと思います。
お礼
レスポンスの例まで示していただきまして、ありがとうございました。 既に通常の抽出としてはうまくいっていたのですが、 レスポンスで問題がおきていました。 参考にさせていただきます。ありがとうございましたm(_ _)m