【问题标题】:Use NTILE function over a rolling window in BigQuery (rolling binning / rolling quantile)在 BigQuery 中的滚动窗口上使用 NTILE 函数(滚动分箱/滚动分位数)
【发布时间】:2021-08-26 08:12:16
【问题描述】:

我有一个简单的表,其中包含时间列(1 分钟频率)和另一列浮点值,我们称之为 A 列。 我的目标是在 BigQuery 中创建一个执行以下操作的查询:

对于每一行,查看前 24 小时和后 24 小时的窗口,并获取作为窗口中心的特定行的相关“桶号”(如NTILE(5) func)。

我正在尝试实现“滚动分箱” - 类似于“滚动分位数”(如 pandas Rolling Quantile) 但带有箱号。我可以在 python 中非常简单地使用pd.DataFrame.rolling.apply 和用于分箱和返回值的自定义函数,但我想使用 BigQuery 来完成。

我在结合 NTILE 函数和滚动窗口时遇到问题。

我能够创建一个滚动窗口(在文档中称为Analytic function)并执行简单的聚合,例如使用平均值

SELECT Time, AVG(A)
OVER (ORDER BY UNIX_SECONDS(Time) ASC RANGE BETWEEN 86400 PRECEDING AND 86400 FOLLOWING) as rolling_avg_24_hours_each_side
FROM `my_project.my_table`

(86400 来自一小时内的 3600 秒 * 24 小时。有没有使用幻数的替代方法?)

在我的整个表格上使用NTILE(5) 函数很容易,但我不能在滚动窗口中使用它。

正如Numbering functions 的文档所述,不允许使用window_frame_clause,因此我不能将RANGE... 语句与NTILE 结合使用。

所以我的主要问题是如何将NTILE 函数与滚动窗口结合起来,或者是否有其他解决方案可以实现滚动窗口的“滚动分箱”?

【问题讨论】:

    标签: sql google-bigquery


    【解决方案1】:

    据我所知,在 BigQuery 中没有简单的方法可以做到这一点。以下方法并不简单,但它可能适用于您的情况。首先将每个窗口所需的行放在一起:

    select t.time, t.a, array_agg(t2.a) as window_a
    from `my_project.my_table` t join
         `my_project.my_table` t2
         on t2.time >= date_add(t.time, interval -24 hour) and
            t2.time < date_add(t.time, interval 24 hour)
    group by t.time, t.a;
    

    然后手动计算图块:

    with t as (
          select t.time, t.a, array_agg(t2.a) as window_a
          from `my_project.my_table` t join
               `my_project.my_table` t2
               on t2.time >= datetime_add(t.time, interval -24 hour) and
                  t2.time < datetime_add(t.time, interval 24 hour)
          group by t.time, t.a
         )
    select t.*,
           (select ceiling(min(case when t.a = a2 then seqnum end) * 5.0 / max(cnt))
            from (select a2,
                         row_number() over (order by a2) as seqnum,
                         count(*) over () as cnt
                  from unnest(t.window_a) a2
                 ) w
           ) as rolling_tile
    from t;
    

    【讨论】:

    • 这个sn-p返回错误“SELECT list expression references table alias a2 which is not grouped and aggregated”
    • 然而,将滚动窗口组合为数组的技巧很有帮助!我设法通过执行select t.time, t.a, a2 as value, NTILE(5) OVER (PARTITION BY t.time ORDER BY a2) as bin, from t CROSS JOIN unnest(t.window_a) a2 ) 直接执行 NTILE(无需手动计算图块),然后使用另一个带有 distinct 的选择来获得我想要的。你想编辑你的答案,还是我应该自己发布另一个答案?
    • @Roim 。 . .我确定了答案。
    • 谢谢,这行得通。我还在下面添加了我自己的答案,即在您建议的窗口上使用 NTILE。
    【解决方案2】:

    Gordon Linoff 的答案有效,通过使用他的滚动窗口技巧,我设法直接应用 NTILE 函数,而不是按照建议“手动”计算它。

    第一部分保持不变,只是创建了窗口。 接下来,我们可以在表之间的CROSS JOIN 上应用NTILE 函数:

    select t.time, t.a, a2 as value, NTILE(5) OVER (PARTITION BY t.time ORDER BY a2) as bin, from t CROSS JOIN unnest(t.window_a) a2
    

    结果是一个包含一些重复行的表。根据我的需要,我可以使用 Min(bin)DISTINCT 消除重复项。

    我的完整查询:

    with t as (
          select t.time, t.a, array_agg(t2.a) as window_a
          from `my_project.my_table` t join
               `my_project.my_table` t2
               on t2.time >= datetime_add(t.time, interval -24 hour) and
                  t2.time < datetime_add(t.time, interval 24 hour)
          group by t.time, t.a
         )
    select distinct time, Min(bin) from (select t.time, t.a, a2 as value, NTILE(5) OVER (PARTITION BY t.time ORDER BY a2) as bin, from t CROSS JOIN unnest(t.window_a) a2)
    

    【讨论】:

      猜你喜欢
      • 2019-05-24
      • 2021-03-11
      • 2018-09-02
      • 2023-04-08
      • 2019-05-16
      • 2016-08-02
      • 2020-05-22
      • 1970-01-01
      • 2022-11-18
      相关资源
      最近更新 更多