トップページに戻る    次のSQLパズルへ    前のSQLパズルへ

10-101 直前の値と等しかったら削除

SQLパズル

ABCTable
ColA  ColB  ColC
----  ----  ----
 101     1    10
 103     1    10  ←削除対象
 105     1    11
 106     1    11  ←削除対象
 108     1    10
 102     2    11
 104     2    11  ←削除対象
 107     2    12
 109     2    12  ←削除対象

order by ColB,ColA
でソートした時に、
直前のレコードとColCが等しいレコードを削除する。

こちらを参考にさせていただきました


データ作成スクリプト

create Table ABCTable(
ColA number(3),
ColB number(1),
ColC number(2),
primary key(ColA));

insert into ABCTable values(101,1,10);
insert into ABCTable values(103,1,10);
insert into ABCTable values(105,1,11);
insert into ABCTable values(106,1,11);
insert into ABCTable values(108,1,10);
insert into ABCTable values(102,2,11);
insert into ABCTable values(104,2,11);
insert into ABCTable values(107,2,12);
insert into ABCTable values(109,2,12);
commit;


SQL

--■■■分析関数を使わない方法■■■
delete from ABCTable a
 where ColC = (select b.ColC
                  from (select c.ColA,c.ColB,c.ColC
                          from ABCTable c
                        order by c.ColB desc,c.ColA desc) b
                 where (b.ColB < a.ColB
                    or (b.ColB = a.ColB and b.ColA < a.ColA))
                   and RowNum = 1);

--■■■分析関数を使う方法■■■
delete from ABCTable
 where RowID in (select Row_ID
                   from (select ColC,RowID as Row_ID,
                         Lag(ColC) over(order by ColB,ColA) as LagColC
                         from ABCTable)
                  where ColC = LagColC);

--■■■複数列in述語を使う方法■■■
delete from ABCTable
where (RowID,ColC)
in (select RowID,Lag(ColC) over(order by ColB,ColA)
      from ABCTable);


解説

分析関数を使わない方法では、
インラインビューで
order by ColB,ColA
のascとdescを入れ替えた逆ソートを行って、
RowNum=1を指定して直前の値を取得してます。