You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Snowflake中如何用窗口函数实现可变时间窗口求和?

可变窗口求和的Snowflake实现方案

你最初尝试的窗口函数写法在Snowflake中不可行——Snowflake要求窗口边界(rows/range between ...)必须是常量值(比如固定数字、固定时间间隔),不能引用列变量(比如lookback)。但可以通过以下两种方式用窗口函数实现你的需求:

方案一:前缀和差值法(推荐,性能更优)

利用累计求和(前缀和)的特性,区间[billing_period_start, snapshot_date]的请求总和等于「截止到snapshot_date的累计请求数」减去「截止到billing_period_start前一天的累计请求数」。

步骤1:计算用户每日请求的累计前缀和

with user_requests_cumulative as (
    select
        user_id,
        request_date,
        total_requests,
        -- 计算每个用户从最早日期到当前日期的累计请求数
        sum(total_requests) over (
            partition by user_id
            order by request_date
            rows between unbounded preceding and current row
        ) as cumulative_requests
    from user_daily_requests
)

步骤2:关联订阅快照表计算周期内总和

select
    s.snapshot_date,
    s.user_id,
    s.billing_period_start,
    s.billing_period_end,
    -- 用当前快照日期的累计值,减去计费周期前一天的累计值,得到周期内总和
    coalesce(rc_current.cumulative_requests, 0)
    - coalesce(rc_prev.cumulative_requests, 0) as num_requests_in_period
from subscription_snapshot s
-- 关联到当前快照日期的累计请求数
left join user_requests_cumulative rc_current
    on s.user_id = rc_current.user_id
    and rc_current.request_date = s.snapshot_date
-- 关联到计费周期开始前一天的累计请求数
left join user_requests_cumulative rc_prev
    on s.user_id = rc_prev.user_id
    and rc_prev.request_date = dateadd(day, -1, s.billing_period_start)

方案二:窗口内条件求和

先将订阅快照表和请求日志表按用户关联,再在窗口内通过条件判断筛选出计费周期内的请求并求和:

with combined_data as (
    select
        s.snapshot_date,
        s.user_id,
        s.billing_period_start,
        s.billing_period_end,
        r.request_date,
        coalesce(r.total_requests, 0) as total_requests
    from subscription_snapshot s
    left join user_daily_requests r
        on s.user_id = r.user_id
)
select
    snapshot_date,
    user_id,
    billing_period_start,
    billing_period_end,
    -- 在窗口内仅对计费周期内的请求求和
    sum(case
        when request_date between s.billing_period_start and s.snapshot_date
        then total_requests
        else 0
    end) over (
        partition by user_id, snapshot_date
    ) as num_requests_in_period
from combined_data
group by snapshot_date, user_id, billing_period_start, billing_period_end, request_date, total_requests

补充说明

你之前的关联逻辑存在笔误:r.request_data应为r.request_date,且正确的关联条件应该是s.billing_period_start <= r.request_date and r.request_date <= s.snapshot_date,而非你写的r.request_data < s.billing_period_start(这会筛选出计费周期之前的请求,和需求相反)。

内容的提问来源于stack exchange,提问作者Rafael Barbosa

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 00:32:33