Months_Between是一个内置的日期操纵函数,用于计算两个日期相隔的月份数。Oracle文档的介绍如下:
MONTHS_BETWEEN returns number of months between dates date1 and date2. The
month and the last day of the month are defined by the parameter NLS_CALENDAR. If
date1 is later than date2, then the result is positive. If date1 is earlier than date2, then
the result is negative. If date1 and date2 are either the same days of the month or both
last days of months, then the result is always an integer. Otherwise Oracle Database
calculates the fractional portion of the result based on a 31-day month and considers
the difference in time components date1 and date2.
总结一下可以归纳出以下几点:
- Months_Between总是计算date1 - date2
- Months_Between在两种情况下返回整数:
- date1和date2的日相同(eg. 2023/05/07和2023/06/07)
- date1和date2都是月份的最后一天(eg. 2023/02/28和2023/03/31)
- 当参数不满足返回整数的条件时,计算结果的整数部分是两日期相隔的整月数,剩余不足整月的天数,将除以31作为小数部分
通过一些例程来理解上面第三条:
例程1:计算2023/01/01到2023/03/02
1月1日至3月1日为整两个月,余一天,1/31=0.032258064516129
SQL> SELECT Months_Between(DATE '2023-03-02',
2 DATE '2023-01-01')
3 FROM dual;
MONTHS_BETWEEN(DATE'2023-03-02',DATE'2023-01-01')
-------------------------------------------------
2.03225806451613
例程2:计算2023/03/01到2023/01/02(负数)
3月1日到2月1日为整-1月,余30天,30/31=0.967741935483871
SQL> SELECT Months_Between(DATE '2023-01-02',
2 DATE '2023-03-01')
3 FROM dual;
MONTHS_BETWEEN(DATE'2023-01-02',DATE'2023-03-01')
-------------------------------------------------
-1.96774193548387
这样的算法不能总是令人满意,比如计算2023/01/31至2023/02/28时得知是一个月,而向前加一天从2023/01/30算起结果却不及一个月了,更有趣的是继续向前加到2023/01/28这一天结果又成了一个月(与此同时这四个起始日期用add_months加一个月结果都是2023/02/28)
SQL> SELECT Months_Between(DATE '2023-02-28', DATE '2023-01-31') a1,
2 Months_Between(DATE '2023-02-28', DATE '2023-01-30') a2,
3 Months_Between(DATE '2023-02-28', DATE '2023-01-29') a3,
4 Months_Between(DATE '2023-02-28', DATE '2023-01-28') a4
5 FROM dual;
A1 A2 A3 A4
----- -------------------- -------------------- -----
1 0.935483870967742 0.967741935483871 1