Oracle の add_months を SQL Server dateadd(month, ~) の結果と同じにするのを考えてみる
twitter で見かけたのでちょっと考えてみる。
select dateadd(month, 1, cast('2016/02/29' as date)) -- 2016/03/29
select add_months('2016/02/29', 1) from dual -- 2016/3/31
足す前の日付と足した後の日付の 日 の部分が違った場合で、足した後の方が大きい時だけ問題になるで良いのかな。
- 日が同じ => 問題無し
- 日が違って、足した時の方が小さい => 足す前の 日 が足した後の月に存在しない 例:1/30 に 1ヶ月足したら 2/28 or 2/29 になるパターン
- 日が違って、足した時の方が大きい => 足す前が月末日、足す前の月の日数が足した後の月の日数より少ない。例:4/30 に 1ヶ月足したら 5/31
最後のパターンだけ差し替えるとこんな感じ。*1
create or replace function ADD_MONTHS_SQLSERVER(target date, plus number) return date is result date; begin select add_months(target, plus) into result from dual; select case when to_char(result, 'DD') > to_char(target, 'DD') then to_date(to_char(result, 'YYYYMM') || to_char(target, 'DD'), 'YYYYMMDD') else result end into result from dual; return result; end;
function 作るのいやだったらこんな感じ?
select case when to_char(add_months(sysdate, 2), 'DD') > to_char(sysdate, 'DD') then to_date(to_char(add_months(sysdate, 2), 'YYYYMM') || to_char(sysdate, 'DD'), 'YYYYMMDD') else add_months(sysdate, 2) end as add_months_sqlserver from dual
LAST_DAY とか使うかなーと思ったけど、そうでもなかった。
※雰囲気動くとこまでしか確認してないから利用は自己責任で!
*1:時刻は考慮してない