70973


oracle sqlを使っています。  
plsqlで実装しています。

今データテーブルがあり、主キーが4つあります。主キーの4つ目がバージョンになっており、「主キー3つが同じで、主キー４（バージョン）が最新のレコードのみを残す。それ以外は削除する。」SQLを作成したいです。

どのようになりますでしょうか？

私が試しているのは以下です。

[code]

    with new_version(
    select 主1,主2,主3,max(主4) as 主4
    from hogeTable 
    group by 主1,主2,主3
    )
    --上記で取得したデータ以外を削除する
    
[/code]

ただsqlに慣れておらず、詰まっております。このやり方では良くないかもしれません。またplsqlで実装しており、for文を使うことと参考にありました。上記のselect文の結果は複数レコードあります。

[code]

    主1 主2 主3 主4
    S1 a   b   1
    S1 a   c   1
    S2 a   b   3
    S2 a   c   1
    .
    .
    .
    
    
[/code]

のようにです。  
S1ab0 や S2ab2 は表示されていない状態です（主4（バージョン）が古いため）。この表示されていないレコードだけ削除したいです。

それらを踏まえて、アドバイス頂けると助かります。


CC BY-SA 4.0
2020-10-06T16:14:42.507
70970
2020-10-07T00:50:02.807
2020-10-06T16:26:21.910
40231
40231
question
sql oracle plsql
主キー四つの場合、主キーの一部が最新のもの以外は削除するSQLが書きたい


考え方は合っています。  
with句の中で書かれたSQLも最新レコードを取得するSQLとして正しいです。

ご質問のSQLと[`not exists`](http://oracle.se-
free.com/dml/01_exists.html)を組み合わせることで最新レコード以外の対象を取得可能です。  
具体的なコードは書きませんが、上記のSQLで取得したレコードに対してカーソルを作成し、for文で1行ずつdeleteすることができます。

なお、私ならばfor文も`group by`も使わずに下記の副問い合わせを使ったSQLで対応します。

[code]

    -- このSQLを使用する前に下記のDDL文を実行しておくこと
    delete from HOGE src
    where  KEY4 < (select max(KEY4) from HOGE tmp where tmp.KEY1 = src.KEY1 and tmp.KEY2 = src.KEY2 and tmp.KEY3 = src.KEY3)
    
[/code]

計測していませんが、1回のSQLで対応しているためfor文を使った削除より速度もメモリ消費も優れている可能性が高いです。

[code]

    -- DDL文
    create table HOGE (
     KEY1 VARCHAR2(2),  KEY2 CHAR(1), KEY3 CHAR(1), KEY4 NUMBER(1),
     constraint PK_HOGE primary key(KEY1, KEY2, KEY3, KEY4) using index
    );
    /
    insert into HOGE values('S1', 'a', 'b', 0);
    /
    insert into HOGE values('S1', 'a', 'b', 1);
    /
    insert into HOGE values('S2', 'x', 'y', 0);
    /
    insert into HOGE values('S2', 'x', 'y', 1);
    /
    insert into HOGE values('S2', 'x', 'y', 2);
    /
    insert into HOGE values('S2', 'x', 'y', 3);
    /
    
[/code]


CC BY-SA 4.0
2020-10-07T00:50:02.807
70973
2020-10-07T00:50:02.807
9820
70970
answer