Athena与Spark SQL计算月份差结果不一致,如何实现统一?
Athena与Spark SQL日期差计算结果统一方案
问题根源
两者计算逻辑存在本质差异:
- Athena的
date_diff('month', start, end):仅对比年份和月份的整数差,完全忽略日部分。比如2022-12-29到2023-02-28,直接计算(2023*12+2) - (2022*12+12) = 2,返回结果2。 - Spark的
months_between(end, start):计算两个日期的实际月份跨度(含小数),2023-02-28到2022-12-29实际约1.967个月,经floor取整后得到1。
统一结果的两种方案
方案1:让Spark SQL结果与Athena一致(返回2)
模拟Athena的年月整数差逻辑,直接计算年月的数值差:
spark.sql(""" select (year(cast('2023-02-28' as date))*12 + month(cast('2023-02-28' as date))) - (year(cast('2022-12-29' as date))*12 + month(cast('2022-12-29' as date))) """).show(5,0)
计算逻辑:(2023*12+2) - (2022*12+12) = 24278 - 24276 = 2,与Athena结果完全匹配。
方案2:让Athena结果与Spark SQL一致(返回1)
模拟Spark的floor(months_between)逻辑,有两种实现方式:
方式A:按平均每月天数计算
select floor(date_diff('day', cast('2022-12-29' as date), cast('2023-02-28' as date)) / 30.4375)
注:30.4375为平年平均每月天数(365/12),计算得59/30.4375≈1.938,经floor取整后返回1。
方式B:按日部分判断是否满整月
更精准的逻辑:若结束日期的日≥开始日期的日,则取年月差;否则年月差减1:
select case when extract(day from cast('2023-02-28' as date)) >= extract(day from cast('2022-12-29' as date)) then date_diff('month', cast('2022-12-29' as date), cast('2023-02-28' as date)) else date_diff('month', cast('2022-12-29' as date), cast('2023-02-28' as date)) - 1 end
因28<29,最终返回2-1=1,与Spark结果一致。
内容的提问来源于stack exchange,提问作者Hannah
相关产品推荐
相关产品推荐

