类别:

日期和时间函数

MONTHS_BETWEEN

返回两个 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

要减去的日期。

返回

表示两个日期之间月数的 FLOAT 数。

该数字的计算方法如下:

  • FLOAT 数的整数部分是使用输入值的年和月部分计算的。

  • 在大多数情况下,分数部分是使用输入值的日期和时间部分计算的。(在计算月的分数时,该函数将每个月的长度视为 31 天。)

    但是,有两个例外:

    • 如果月份的日相同(例如 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)

  • 可以对一个输入参数使用 DATE 值,并对另一个输入参数使用 TIMESTAMP 值。

  • 如果使用一个或多个 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 月 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

下一个示例显示了分数月的差异。

  • 对于第一列,向该函数传递两个日期。

  • 对于第二列,向该函数传递两个时间戳,它们表示用于第一列的那两个日期,但时间不同。由于时间上的差异,第二列的差异大于第一列。

  • 对于第三列,向该函数传递两个时间戳,它们表示各自月份的同一日。这会导致该函数忽略两个时间戳之间的任何时间差异,因此分数部分为 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 作为结果的分数部分。

  • 对于第二列,输入日期表示不同月份的不同日(并且都不是当月最后一日),因此该函数会计算结果的分数部分。

  • 对于第三列,输入日期表示两个不同月份中每一个的最后一日,因此该函数再次返回 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
语言: 中文