来自documentation on MONTHS_BETWEEN:
MONTHS_BETWEEN 返回日期 date1 和 date2 之间的月数。如果date1 晚于date2,则结果为正。如果date1 早于date2,则结果是否定的。如果date1 和date2 是一个月中的同一天或两个月的最后一天,则结果始终为整数。否则,Oracle 数据库会根据 31 天的月份计算结果的小数部分,并考虑时间分量 date1 和 date2 的差异。
您可以使用以下方法“修复”MONTHS_BETWEEN,这样当月的日期相同(或者它们都是月的最后一天)时,它并不总是使用整数值:
MONTHS_BETWEEN( end_date, start_date )
+
CASE
WHEN EXTRACT( DAY FROM start_date ) = EXTRACT( DAY FROM end_date )
OR ( start_date = LAST_DAY( start_date ) AND end_date = LAST_DAY( end_date ) )
THEN ( end_date
- ADD_MONTHS( start_date, MONTHS_BETWEEN( end_date, start_date ) )
) / 31
ELSE 0
END
因此,您的查询将是:
SELECT start_date,
end_date,
CEIL(
(
MONTHS_BETWEEN( end_date, start_date )
+
CASE
WHEN EXTRACT( DAY FROM start_date ) = EXTRACT( DAY FROM end_date )
OR ( start_date = LAST_DAY( start_date ) AND end_date = LAST_DAY( end_date ) )
THEN ( end_date
- ADD_MONTHS( start_date, MONTHS_BETWEEN( end_date, start_date ) )
) / 31
ELSE 0
END
)
/ 12
) AS years
FROM test_data;
对于一些测试数据:
CREATE TABLE test_data ( start_date, end_date ) AS
SELECT DATE '2019-07-01',
DATE '2020-07-01' + INTERVAL '15:30:00' HOUR TO SECOND
FROM DUAL
UNION ALL
SELECT DATE '2019-07-31',
DATE '2020-02-29' + INTERVAL '15:30:00' HOUR TO SECOND
FROM DUAL
UNION ALL
SELECT DATE '2019-02-28',
DATE '2020-02-29' + INTERVAL '15:30:00' HOUR TO SECOND
FROM DUAL;
这个输出:
START_DATE | END_DATE |年
:----------------- | :----------------- | ----:
2019-07-01 00:00:00 | 2020-07-01 15:30:00 | 2
2019-07-31 00:00:00 | 2020-02-29 15:30:00 | 1
2019-02-28 00:00:00 | 2020-02-29 15:30:00 | 2
db小提琴here