トップページに戻る
次のSQLパズルへ
前のSQLパズルへ
8-53 nth_value関数を模倣
SQLパズル
emu_nthテーブル
ID Val
-- ----
1 null
1 999
1 888
1 777
2 null
2 null
2 666
3 null
3 null
4 555
4 444
4 333
5 null
5 222
5 222
以下の、nth_value関数(respect nulls)と、
nth_value関数(ignore nulls)を使用した
Oracle11gR2のSQLと同じ結果を、Oracle10gR2のSQLで取得する。
select ID,Val,
nth_value(Val,3) from Last
over(partition by ID
order by Val Rows between Unbounded Preceding and Unbounded Following) as resp_null,
nth_value(Val,3) from Last ignore nulls
over(partition by ID
order by Val Rows between Unbounded Preceding and Unbounded Following) as igno_null
from emu_nth
order by ID,Val desc;
出力結果
ID Val resp_null igno_null
-- ---- --------- ---------
1 null 888 777
1 999 888 777
1 888 888 777
1 777 888 777
2 null 666 null
2 null 666 null
2 666 666 null
3 null null null
3 null null null
4 555 333 333
4 444 333 333
4 333 333 333
5 null 222 null
5 222 222 null
5 222 222 null
データ作成スクリプト
create table emu_nth(ID,Val) as
select 1,null from dual union all
select 1, 999 from dual union all
select 1, 888 from dual union all
select 1, 777 from dual union all
select 2,null from dual union all
select 2,null from dual union all
select 2, 666 from dual union all
select 3,null from dual union all
select 3,null from dual union all
select 4, 555 from dual union all
select 4, 444 from dual union all
select 4, 333 from dual union all
select 5,null from dual union all
select 5, 222 from dual union all
select 5, 222 from dual;
SQL
--■■■nulls Lastでソートする方法■■■
select ID,Val,
max(decode(resp_null,3,Val)) over(partition by ID) as resp_null,
max(decode(igno_null,3,Val)) over(partition by ID) as igno_null
from (select ID,Val,
Row_Number() over(partition by ID order by Val desc) as resp_null,
Row_Number() over(partition by ID order by Val desc nulls Last) as igno_null
from emu_nth)
order by ID,Val desc;
--■■■nullなら別のパーティションにする方法■■■
select ID,Val,
max(decode(resp_null,3,Val)) over(partition by ID) as resp_null,
max(decode(igno_null,3,Val)) over(partition by ID) as igno_null
from (select ID,Val,
Row_Number() over(partition by ID order by Val desc) as resp_null,
Row_Number() over(partition by ID,nvl2(Val,0,1) order by Val desc) as igno_null
from emu_nth)
order by ID,Val desc;
解説
nth_value関数は、Row_Number関数がN番目の値を返すので、
Row_Number関数を使ってます。