在 Snowflake 中获取 Impala 等价于 MONTHS_BETWEEN()

Get Impala equivalent of MONTHS_BETWEEN() in Snowflake

我在将查询从 Impala 迁移到 Snowflake 时遇到问题:

Impala

SELECT period
    , now() as dt_today
    , MONTHS_BETWEEN(now(), period) as mb
FROM my_table

产量

period                  dt_today                        mb
--------------------------------------------------------------------------
2018-10-30T21:43:57Z    2020-02-21 10:21:12.827383000   15.709677419354838

雪花

SELECT period
    , CURRENT_TIMESTAMP() as dt_today
    , DATEDIFF('month', CURRENT_TIMESTAMP(), period) as mb
FROM my_table

产量

period                  dt_today                        mb
--------------------------------------------------------------------------
2018-10-30T21:43:57Z    2020-02-21 10:21:12.827383000   16

现在,从 Snowflake documentation 我了解到当在 DATEDIFF 中指定 month 时,Snowflake 只会 "use the month and year from the date" 这意味着差异并不像与 Impala 一样准确。 我试过实现一个 proxy,比如取月差,然后应用一些计算来得到浮点部分,但我仍然得到错误的月数:

DATEDIFF('month', period, CURRENT_TIMESTAMP()) + (GREATEST(DAY(period), DAY(CURRENT_TIMESTAMP())) -  LEAST(DAY(period), DAY(CURRENT_TIMESTAMP()))) / 31

以及以下内容以获得更精确的信息,但仍然不正确:

DATEDIFF('day', period, CURRENT_TIMESTAMP())/31 + (GREATEST(DAY(period), DAY(CURRENT_TIMESTAMP())) -  LEAST(DAY(period), DAY(CURRENT_TIMESTAMP()))) / 31

问题:如何在 Snowflake 中准确复制 Impala 的 MONTHS_BETWEEN()

您的差异需要多精确?

因为我的第一个电话是减去两个日期(得到天数的差异) - 或者你可以只使用 datediff 只是提取日期 - 然后从那里开始(如果近似值可以,则除以 30/31或者如果我需要精确的解决方案,可以使用一些更复杂的计算)

你的解决方案是不正确的,因为如果你假设 12 月 31 日和 1 月 1 日,即使在随后的日子里,datediff 中的月份也会相差 1 - 这两个月份都会在 datediff 中给出“1”年月日。

TL;DR

IFF(DAY(DATE1) >= DAY(DATE2), DATEDIFF('month', DATE2, DATE1), DATEDIFF('month', DATE2, DATE1) - 1)
+
IFF(DAY(DATE1) >= DAY(DATE2), (GREATEST(DAY(DATE1), DAY(DATE2)) - LEAST(DAY(DATE1), day(DATE2))) / 31, 1 - (GREATEST(DAY(DATE1), DAY(DATE2)) - LEAST(DAY(DATE1), DAY(DATE2))) / 31)

Impala MONTHS_BETWEEN(DATE1, DATE2) 函数的工作原理如下:

  • MONTHS_BETWEEN('2019-04-13', '2019-02-10') 产量 2.09672 整月 + 3/31=0967
  • MONTHS_BETWEEN('2019-04-13', '2019-02-03') 产量 1.77411 整月 + 1-(7/31)=0967

现在我们知道 Snowflake DATEDIFF(DATE1, DATE3) 应用了一个简单的逐月操作:

  • DATEDIFF('month', '2019-04-13', '2019-02-10') 产生 2 (04 - 02)
  • DATEDIFF('month', '2019-04-13', '2019-02-03') 产生 2 (04 - 02)

为了使用 Snowflake 函数获得 Impala 的 MONTHS_BETWEEN 的整数部分,我们应用以下逻辑:

IFF(DAY(DATE1) >= DAY(DATE2), DATEDIFF('month', DATE2, DATE1), DATEDIFF('month', DATE2, DATE1) - 1)

为了使用 Snowflake 函数获得 Impala 的 MONTHS_BETWEEN 的小数部分,我们应用以下逻辑:

IFF(DAY(DATE1) >= DAY(DATE2), (GREATEST(DAY(DATE1), DAY(DATE2)) - LEAST(DAY(DATE1), day(DATE2))) / 31, 1 - (GREATEST(DAY(DATE1), DAY(DATE2)) - LEAST(DAY(DATE1), DAY(DATE2))) / 31)

我们只需将它们相加即可得到 Impala 的准确值:

IFF(DAY(DATE1) >= DAY(DATE2), DATEDIFF('month', DATE2, DATE1), DATEDIFF('month', DATE2, DATE1) - 1)
+
IFF(DAY(DATE1) >= DAY(DATE2), (GREATEST(DAY(DATE1), DAY(DATE2)) - LEAST(DAY(DATE1), day(DATE2))) / 31, 1 - (GREATEST(DAY(DATE1), DAY(DATE2)) - LEAST(DAY(DATE1), DAY(DATE2))) / 31)

Snowflake 原生支持它:4.42 Release Notes

MONTHS_BETWEEN

MONTHS_BETWEEN( <date_expr1> , <date_expr2> )

Returns the number of months between two DATE or TIMESTAMP values.