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

5-56 nullを最も小さいとし、最小値の行を取得

SQLパズル

CodeTable
Code      Day1  Val
----  --------  ---
aaaa  2007/3/1  100  ←出力対象
aaaa  2007/3/2  200
aaaa  2007/3/3  300
bbbb  2007/3/4  400  ←出力対象
cccc  null      500  ←出力対象
cccc  2007/3/1  600
cccc  2007/3/2  700
dddd  null      800  ←出力対象

Codeごとに、Day1が最小の行を出力する。
ただし、
Day1の大小比較においては、nullが最も小さいとする。


データ作成スクリプト

create table CodeTable as
select 'aaaa' as Code,to_date('2007/3/1','fmyyyy/mm/dd') as Day1,100 as Val from dual
union select 'aaaa',to_date('2007/3/2','fmyyyy/mm/dd'),200 from dual
union select 'aaaa',to_date('2007/3/3','fmyyyy/mm/dd'),300 from dual
union select 'bbbb',to_date('2007/3/4','fmyyyy/mm/dd'),400 from dual
union select 'cccc',                              null,500 from dual
union select 'cccc',to_date('2007/3/1','fmyyyy/mm/dd'),600 from dual
union select 'cccc',to_date('2007/3/2','fmyyyy/mm/dd'),700 from dual
union select 'dddd',                              null,800 from dual;


SQL

--■■■分析関数を使う方法1■■■
select distinct Code,
First_Value(Day1) over(partition by Code order by Day1 nulls first) as Day1,
First_Value(Val)  over(partition by Code order by Day1 nulls first) as Val
  from CodeTable;

--■■■分析関数を使う方法2■■■
select Code,Day1,Val
from (select Code,Day1,Val,
      Rank() over(partition by Code order by Day1 nulls first) as Rank
        from CodeTable)
where Rank = 1
order by Code;

--■■■分析関数を使わない方法■■■
select Code,Day1,Val
  from CodeTable a
 where Day1 is null
    or Day1 = (select min(b.Day1)
                 from CodeTable b
                where b.Code = a.Code
               having count(*) = count(Day1));


解説

分析関数を使わない方法では、nullの有無を
having count(*) = count(Day1)
で判定してます。

5-40 グループごとに最大値の行を取得