Teradata MONTHS_BETWEEN与GCP DATE_DIFF结果差异求等效函数
实现Teradata MONTHS_BETWEEN等效逻辑的BigQuery(GCP)查询
Teradata的MONTHS_BETWEEN函数会返回包含小数的月份差(基于31天月份计算小数部分,同时支持时间组件),而BigQuery原生的DATE_DIFF仅返回整数月份差。要在GCP上实现完全等效的逻辑,可以自定义函数模拟Teradata的计算规则:
针对DATE类型的等效实现
Teradata的核心规则:
- 若两个日期的日部分相同,或均为当月最后一天,返回整数月份差
- 否则,整数部分为月份差,小数部分为两日差值除以31
对应的BigQuery临时函数:
CREATE TEMP FUNCTION MONTHS_BETWEEN_TERADATA(end_date DATE, start_date DATE) AS ( CASE WHEN (EXTRACT(DAY FROM end_date) = EXTRACT(DAY FROM start_date)) OR (EXTRACT(DAY FROM end_date) = EXTRACT(DAY FROM LAST_DAY(end_date)) AND EXTRACT(DAY FROM start_date) = EXTRACT(DAY FROM LAST_DAY(start_date))) THEN DATE_DIFF(end_date, start_date, MONTH) ELSE DATE_DIFF(end_date, start_date, MONTH) + (EXTRACT(DAY FROM end_date) - EXTRACT(DAY FROM start_date)) / 31 END ); -- 测试示例(返回≈1.03,与Teradata结果一致) SELECT ROUND(MONTHS_BETWEEN_TERADATA(DATE '1995-02-02', DATE '1995-01-01'), 2) AS result;
针对TIMESTAMP类型(含时间组件)的等效实现
如果需要支持时间差的计算(Teradata会将时间差转换为天数的小数部分,再除以31),可以扩展函数:
CREATE TEMP FUNCTION MONTHS_BETWEEN_TERADATA_TS(end_ts TIMESTAMP, start_ts TIMESTAMP) AS ( ROUND( CASE WHEN (EXTRACT(DAY FROM end_ts) = EXTRACT(DAY FROM start_ts)) OR (EXTRACT(DAY FROM end_ts) = EXTRACT(DAY FROM LAST_DAY(end_ts)) AND EXTRACT(DAY FROM start_ts) = EXTRACT(DAY FROM LAST_DAY(start_ts))) THEN DATE_DIFF(DATE(end_ts), DATE(start_ts), MONTH) ELSE DATE_DIFF(DATE(end_ts), DATE(start_ts), MONTH) + (EXTRACT(DAY FROM end_ts) - EXTRACT(DAY FROM start_ts)) / 31 END + TIMESTAMP_DIFF(end_ts, start_ts, SECOND) / (31 * 24 * 60 * 60), 2 ) ); -- 测试带时间的示例 SELECT MONTHS_BETWEEN_TERADATA_TS(TIMESTAMP '1995-02-02 12:00:00', TIMESTAMP '1995-01-01 00:00:00') AS result;
以上函数完全对齐Teradata的MONTHS_BETWEEN计算逻辑,可直接在BigQuery中使用。
内容的提问来源于stack exchange,提问作者S M
相关产品推荐
相关产品推荐

