Snowflake 中滑动 Window 函数的解决方法

Workaround on Sliding Window Function in Snowflake

我偶然发现了一个让我非常头疼的问题,如下所示:

我有一个 table 交易,其中包含来自我们的销售 CRM 的关于该实体的信息。我还有一个 table 公司,其中包含有关与这些交易挂钩的公司的信息。

我被要求计算一个名为 Pipeline Conversion Rate 的指标,其计算公式为: 赢得交易/创造交易

到这里,一切都已经很清楚了。然而,在计算这个指标时,我被要求以滑动 window 函数的方式进行,这意味着只计算前 90 天的指标。问题是要查看分子的最后 90 天,我们需要使用一个日期(创建日期);而在查看分母的前 90 天时,我们应该考虑关闭日期(这两个维度都是交易的一部分 table)。

如果我们可以在 Snowflake 中实现这种 window 功能,就不会有任何问题,如下所示(我知道语法可能不完全是这个,但你明白了):

count(deal_id) over (
  partition by is_inbound, sales_agent, sales_tier, country
  order by created_date range between 90 days preceding and current row
) as created_deals_last_90_days,
count(case when is_deal_won then deal_id end) over (
  partition by is_inbound, sales_agent, sales_tier, country
  order by created_date range between 90 days preceding and current row
) as won_deals_last_90_days

但据我所知我们不能。所以我目前的解决方法如下(取自):

select
  calendar_date,
  is_inbound,
  sales_tier,
  sales_agent,
  country,
  (
   select count(deal_id)
   from deals
   where d.is_inbound = is_inbound
     and d.sales_tier = sales_tier
     and d.sales_agent = sales_agent
     and d.country = country
     and created_date between cal.calendar_date - 90 and cal.calendar_date
   ) as created_deals_last_90_days,
   (
   select count(case when is_deal_won then deal_id end)
   from deals
   where d.is_inbound = is_inbound
     and d.sales_tier = sales_tier
     and d.sales_agent = sales_agent
     and d.country = country
     and closed_date between cal.calendar_date - 90 and cal.calendar_date
   ) as won_deals_last_90_days
from calendar as cal
left join deals as d on cal.calendar_date between d.created_date and d.closed_date

*请注意,我在这里使用 calendar table 作为基数 table,以便查看所有日历日期,因为如果没有它,我可能会说我会错过那些日期没有新的交易(可能在周末发生)。

问题是当我交叉检查原始数据和这个查询的输出时,我没有得到正确的数字,我不知道如何使这个(丑陋的)解决方法,嗯......工作。

欢迎任何想法!

好吧,事实证明它比我预期的要容易得多。经过一些 trial-and-error,我发现唯一可能失败的是外部查询中的 JOIN 条件:

on cal.calendar_date between d.created_date and d.closed_date

这是假设两个日期都需要在范围内,但这个假设是错误的。通过将外部查询的上述部分调整为:

on cal.calendar_date >= d.created_date

它捕获在 calendar_date 或之前创建的所有交易,因此所有这些交易都是必填字段。

保持查询的其余部分不变,并假设任何分区中都没有空值,结果就是我预期的结果。