--■■■カレンダと比較する方法■■■
select date_value,
to_char(add_months(to_date(date_value,'yyyy-mm-dd'),-3),'yyyy') as 年度
from date_test a
where exists(select a.date_value from dual
intersect
select to_char(to_date('20020401','yyyymmdd')+RowNum-1,'yyyy-mm-dd')
from (select 1 from all_catalog where RowNum <= 366*2)
where to_date('20020401','yyyymmdd')+RowNum-1
<= to_date('20040331','yyyymmdd'))
order by date_value;
--■■■短絡orで文字列をチェックする方法■■■
select date_value,年度
from(
select date_value,
to_char(add_months(to_date(
case
when date_value is null then null
when Length(date_value) != Length('yyyy-mm-dd') then null
when translate(date_value,'a-0123456789','a') is not null then null
when Length(Replace(date_value,'-')) != 8 then null
when Replace(date_value,'-') is null then null
when substr(date_value,5,1) != '-' or substr(date_value,8,1) != '-' then null
when to_number(substr(date_value,6,2)) not between 1 and 12 then null
when to_number(substr(date_value,9,2)) >
30+ case when to_number(substr(date_value,6,2)) in(4,6,9,11) then 0 else 1 end
then null
when to_number(substr(date_value,6,2)) = 2
and to_number(substr(date_value,9,2)) >
28+ decode(to_char(to_date(substr(date_value,1,4) || '1231','yyyymmdd'),'ddd'),'366',1,0)
then null
else date_value end,'yyyy-mm-dd'),-3),'yyyy') as 年度
from date_test)
where 年度 between '2002' and '2003'
order by date_value;
--■■■上のクエリで正規表現を使用(10g以降)■■■
select date_value,年度
from(
select date_value,
to_char(add_months(to_date(
case
when date_value is null then null
when not RegExp_Like(date_value,'^[0-9]{4}-[0-9]{2}-[0-9]{2}$') then null
when to_number(substr(date_value,6,2)) not between 1 and 12 then null
when to_number(substr(date_value,9,2)) >
30+ case when to_number(substr(date_value,6,2)) in(4,6,9,11) then 0 else 1 end
then null
when to_number(substr(date_value,6,2)) = 2
and to_number(substr(date_value,9,2)) >
28+ decode(to_char(to_date(substr(date_value,1,4) || '1231','yyyymmdd'),'ddd'),'366',1,0)
then null
else date_value end,'yyyy-mm-dd'),-3),'yyyy') as 年度
from date_test)
where 年度 between '2002' and '2003'
order by date_value;