これからはなすこと
- ADD_MONTHSとDATEADDは条件によって動きが違うこと
- どのような条件下で動きが違うのか
目次
- ADD_MONTHSについて
- DATEADDについて
- 注意点
- 動きの違いを再現
- おわりに
1.ADD_MONTHSについて
ADD_MONTHS関数について以下説明文引用しました。
指定された月数を日付またはタイムスタンプに加算または減算し、月末情報を保持します。
構文.sql
ADD_MONTHS( <date_or_timestamp_expr> , <num_months_expr> );
例
例.sql
SELECT ADD_MONTHS('2023-07-31'::date, 1) AS RESULT;
2.DATEADDについて
次にDATEADD関数について、以下説明文を引用しました。
指定された日付または時刻部分の指定された値を日付、時刻、またはタイムスタンプに追加します。
構文.sql
DATEADD( <date_or_time_part>, <value>, <date_or_time_expr> )
例
例.sql
SELECT DATEADD(month, 1,'2023-07-31') AS RESULT;
3.注意点
公式ドキュメントにはこのような注意点が記載されています。
-
ADD_MONTHSは、MONTHコンポーネントで使用されるDATEADDとは少し異なる結果を返します。
-
ADD_MONTHSとDATEADDの両方で、
結果の月の日数が元の日より少ない場合、
月の結果の日は、結果の月の最後の日です。 -
ADD_MONTHSの場合のみ、
元の日が月の最後の日である場合、
結果の月の日は、結果の月の最後の日になります。
-
ADD_MONTHSとDATEADDの両方で、
上記の注意点を読み解くと、以下のような解釈ができると考えました。
- 月末の日付では動きが変わります。
- (例1)2023年1月31日が元の日付の時、一か月後の結果は2023年2月28日になります。
- (例2)2023年2月28日が元の日付の時、一か月後の結果は2023年3月31日になります。(ADD_MONTHSの場合のみ)
4.動きの違いを再現
実際に上記の通りになるか検証してみました。
1月末の一月後の結果.sql
SELECT
ADD_MONTHS('2023-01-31'::date, 1) AS RESULT,
DATEADD(month, 1,'2023-01-31') AS RESULT2;
2月末の一月後の結果.sql
SELECT
ADD_MONTHS('2023-02-28'::date, 1) AS RESULT,
DATEADD(month, 1,'2023-02-28') AS RESULT2;
結果
注意点通りの結果になっていると思います。
また、マイナス値で日付を遡ることができるのですが、こちらも同じ現象になります。
下記検証結果
3月末の一月前の結果.sql
SELECT
ADD_MONTHS('2023-03-31'::date, -1) AS RESULT,
DATEADD(month, -1,'2023-03-31') AS RESULT2;
2月末の一月前の結果.sql
SELECT
ADD_MONTHS('2023-03-31'::date, -1) AS RESULT,
DATEADD(month, -1,'2023-03-31') AS RESULT2;
5.おわりに
どちらの関数も売上データ等、月末の日付を扱うものに大きく影響を与える関数だと思います。
例えば、任意の日付からLAST_DAY関数で月末日付を表示してから表題の関数を利用するみたいな感じでしょうか・・・
どちらを使うかはケースバイケースですが、この違いを認識しておくことでロジックを組む際の一助になればと思います。