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

10-93 前月の同一日付を取得

SQLパズル

Daysテーブル
年月日
----------
2004/02/28
2004/02/29
2006/01/02
2006/01/31
2006/02/27
2006/02/28
2006/03/29
2006/03/30
2006/03/31
2006/04/30
2006/05/30
2006/05/31

前月の同一日付を出力する。

ただし、
前月の同一日付が、前月の末日を超える場合は、
前月の末日を出力する。

出力結果
年月日      一月前
----------  ----------
2004/02/28  2004/01/28
2004/02/29  2004/01/29
2006/01/02  2005/12/02
2006/01/31  2005/12/31
2006/02/27  2006/01/27
2006/02/28  2006/01/28
2006/03/29  2006/02/28
2006/03/30  2006/02/28
2006/03/31  2006/02/28
2006/04/30  2006/03/30
2006/05/30  2006/04/30
2006/05/31  2006/04/30


データ作成スクリプト

create table Days as
select to_date('20040228','yyyymmdd') as 年月日 from dual
union select to_date('20040229','yyyymmdd') from dual
union select to_date('20060102','yyyymmdd') from dual
union select to_date('20060131','yyyymmdd') from dual
union select to_date('20060227','yyyymmdd') from dual
union select to_date('20060228','yyyymmdd') from dual
union select to_date('20060329','yyyymmdd') from dual
union select to_date('20060330','yyyymmdd') from dual
union select to_date('20060331','yyyymmdd') from dual
union select to_date('20060430','yyyymmdd') from dual
union select to_date('20060530','yyyymmdd') from dual
union select to_date('20060531','yyyymmdd') from dual;


SQL

--■■■to_date関数を使う方法■■■
select 年月日,
to_date(to_char(add_months(年月日,-1),'yyyymm') ||
to_char(Least(extract(day from Last_day(add_months(年月日,-1))),
              extract(day from 年月日)),'FM00'),'yyyymmdd') as 一月前
from Days;

--■■■日付の引き算を使う方法■■■
select 年月日,
年月日 - greatest(extract(day from 年月日),
                  extract(day from last_day(add_months(年月日,-1)))) as 一月前
from Days;


解説

前月の末日と比較して、分岐させてます。