カテゴリ:

日付と時刻の関数

MONTHS_BETWEEN

2つのDATEまたはTIMESTAMP値の間の月数を返します。

たとえば、 MONTHS_BETWEEN('2020-02-01'::DATE, '2020-01-01'::DATE) は1.0を返します。

こちらもご参照ください:

DATEDIFF

構文

MONTHS_BETWEEN( <date_expr1> , <date_expr2> )
Copy

引数

date_expr1

元の日付。

date_expr2

差し引く日付。

戻り値

2つの日付の間の月数を表すFLOAT。

数値は以下のように計算されます。

  • FLOATの整数部分は、入力値の年と月の部分を使用して計算されます。

  • ほとんどの場合、小数部分は入力値の日と時間の部分を使用して計算されます。(月の割合を計算するとき、関数は各月を31日と見なします。)

    ただし、2つの例外があります。

    • 月の日が同じである場合(例:2月28日と3月28日)、 入力値の一方または両方がタイムスタンプであり、時刻が異なっていても 、小数部分はゼロです。

    • 月の日が両方とも月の最後の日である場合(たとえば、2月28日と3月31日)、 月の日が同じでなくても、 小数部分はゼロです。

    たとえば、この関数は、次の日付/タイムスタンプのペアのそれぞれが正確に1.0か月離れていると見なします。

    日付/タイムスタンプ1

    日付/タイムスタンプ2

    注意

    2019-03-01 02:00:00

    2019-02-01 13:00:00

    各月の同じ日。

    2019-03-28

    2019-02-28

    各月の同じ日。

    2019-03-31

    2019-02-28

    各月の最終日。

    2019-03-31 01:00:00

    2019-02-28 13:00:00

    各月の最終日。

使用上の注意

  • 日付(またはタイムスタンプ)d1がd2よりも前の時点を表す場合、 MONTHS_BETWEEN(d1, d2) は負の値を返します。それ以外の場合は、正の値を返します。より一般的には、入力を交換すると符号が逆になります: MONTHS_BETWEEN(d1, d2) = -MONTHS_BETWEEN(d2, d1)

  • 1つの入力パラメーターに DATE 値を使用し、もう1つの入力パラメーターに TIMESTAMP を使用できます。

  • 1つ以上の TIMESTAMP 値を使用しているものの、時刻に基づく小数の差異が必要ない場合は、 TIMESTAMP 式を DATE にキャストします。

  • 整数値のみが必要な場合は、値を切り捨て、丸め、またはキャストできます。例:

    SELECT
        ROUND(MONTHS_BETWEEN('2019-03-31 12:00:00'::TIMESTAMP,
                             '2019-02-28 00:00:00'::TIMESTAMP)) AS MonthsBetween1;
    +----------------+
    | MONTHSBETWEEN1 |
    |----------------|
    |              1 |
    +----------------+
    
    Copy
  • 入力がNULLの場合、結果はNULLになります。

この例は、月全体の違いを示しています。日付の最初のペアは、月の同じ日(15日)になります。日付の2番目のペアは、両方ともそれぞれの月の最後の日です(2月28日と3月31日)。

SELECT
    MONTHS_BETWEEN('2019-03-15'::DATE,
                   '2019-02-15'::DATE) AS MonthsBetween1,
    MONTHS_BETWEEN('2019-03-31'::DATE,
                   '2019-02-28'::DATE) AS MonthsBetween2;
+----------------+----------------+
| MONTHSBETWEEN1 | MONTHSBETWEEN2 |
|----------------+----------------|
|       1.000000 |       1.000000 |
+----------------+----------------+
Copy

次の例は、小数月の違いを示しています。

  • 最初の列では、関数に2つの日付が渡されます。

  • 2番目の列の場合、関数には、最初の列で使用されたものと同じ2つの日付を表す2つのタイムスタンプが渡されますが、時刻は異なります。時間の違いにより、2番目の列の差は1番目の列よりも大きくなっています。

  • 3番目の列では、関数にそれぞれの月の同じ日を表す2つのタイムスタンプが渡されます。これにより、関数はタイムスタンプ間の時間差を無視するため、小数部分は0になります。

SELECT
    MONTHS_BETWEEN('2019-03-01'::DATE,
                   '2019-02-15'::DATE) AS MonthsBetween1,
    MONTHS_BETWEEN('2019-03-01 02:00:00'::TIMESTAMP,
                   '2019-02-15 01:00:00'::TIMESTAMP) AS MonthsBetween2,
    MONTHS_BETWEEN('2019-02-15 02:00:00'::TIMESTAMP,
                   '2019-02-15 01:00:00'::TIMESTAMP) AS MonthsBetween3
    ;
+----------------+----------------+----------------+
| MONTHSBETWEEN1 | MONTHSBETWEEN2 | MONTHSBETWEEN3 |
|----------------+----------------+----------------|
|       0.548387 |       0.549731 |       0.000000 |
+----------------+----------------+----------------+
Copy

月の日が同じ場合(例:2月28日と3月28日)と、月の日が最後の場合(例:2月28日と3月31日)の 両方 で、関数が月を整数で返すという事実は特に、ペア内で最初の日付を増やしても、必ずしも出力値が増えるわけではないという、非直観的な動作につながります。この例では、最初の日付が3月28日から3月30日に、次に3月31日まで増加するにつれて、差は1.0からより大きな数値に増加し、その後1.0まで減少します。

  • 最初の列では、入力日は異なる月の同じ日を表すため、関数は結果の小数部分に対して 0 を返します。

  • 2番目の列の場合、入力日は異なる月の異なる日を表します(両方とも月の最後の日ではありません)。したがって、関数は結果の小数部分を計算します。

  • 3番目の列の場合、入力日は2つの異なる月のそれぞれの最終日を表すため、関数は結果の小数部分に対して再び 0 を返します。

SELECT
    MONTHS_BETWEEN('2019-03-28'::DATE,
                   '2019-02-28'::DATE) AS MonthsBetween1,
    MONTHS_BETWEEN('2019-03-30'::DATE,
                   '2019-02-28'::DATE) AS MonthsBetween2,
    MONTHS_BETWEEN('2019-03-31'::DATE,
                   '2019-02-28'::DATE) AS MonthsBetween3
    ;
+----------------+----------------+----------------+
| MONTHSBETWEEN1 | MONTHSBETWEEN2 | MONTHSBETWEEN3 |
|----------------+----------------+----------------|
|       1.000000 |       1.064516 |       1.000000 |
+----------------+----------------+----------------+
Copy

この例は、パラメーターの順序を逆にすると、結果の符号が逆になることを示しています。

SELECT
    MONTHS_BETWEEN('2019-03-01'::DATE,
                   '2019-02-01'::DATE) AS MonthsBetween1,
    MONTHS_BETWEEN('2019-02-01'::DATE,
                   '2019-03-01'::DATE) AS MonthsBetween2
    ;
+----------------+----------------+
| MONTHSBETWEEN1 | MONTHSBETWEEN2 |
|----------------+----------------|
|       1.000000 |      -1.000000 |
+----------------+----------------+
Copy