PostgreSQLでMONTHS_BETWEEN

/ db

2つの日付から経過月数を求めたい場合、Oracle には MONTHS_BETWEEN という便利なファンクションが用意されているのだけど、あいにく PostgreSQL にそういったものは無い。

「こんなもの、きっと誰かが考えてくれているだろう」と検索したら、やっぱりあった。

[ThinkIT] 第8回:ファンクションの移行(2)

CREATE FUNCTION MONTHS_BETWEEN(DATE,DATE)
  RETURNS NUMERIC AS
'SELECT to_number((date($1)-date($2)),
                  ''999999999'')/31 '
LANGUAGE 'sql'; 

記事では上記のように関数定義しているのだけど、このように常に 31 で除算すると、2008/3/21 と 2008/1/4 の差がおよそ 2.48 となる。切り捨てて2ヵ月間と見るか、切り上げて3ヵ月間と見るか、四捨五入して2ヵ月間と見るか。四捨五入するならば、実際は2ヵ月17日の差なので、「3ヶ月間」とする方が、みんなの求めるものに近いと思う。

どうするか。

日付の差を操作する場合は、age関数を使いましょう。

-- 切捨する場合
SELECT extract(month FROM age(date1,date2));
-- 切上する場合
SELECT extract(month FROM age(date1,date2) + interval '@ 1 month');
-- 四捨五入(15日以前は切捨、16日以降は切上)
SELECT extract(month FROM age(date1 + interval '@ 0.5 month',date2);

実際の現場では、4/10と5/10という2つの日付について、1ヵ月とみなす場合もあろうし、2ヵ月としたいケースもあるんじゃないかと思います。その辺は、上記参考に柔軟にイジイジすると良いと思います。

このエントリーのトラックバックURL
http://www.deftrash.com/admin/mt4/mt-tb.cgi/501