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

在Snowflake中将数值转换为累计值的SQL实现需求

问题描述

现有如下结构的表(示例数据):

Refstart_dateend_datetypeseat
ABCDEF11112023-12-22 09:11:142024-01-31 23:59:59recurring1
ABCDEF11112024-01-02 06:42:552024-02-22 23:59:59prorata47
ABCDEF11112024-01-11 12:02:462024-02-22 23:59:59prorata24
ABCDEF11112024-12-22 00:00:002025-01-31 23:59:59renew72
ABCDEF11112024-12-23 08:23:54cancelled-72

需要使用Snowflake SQL生成如下结果:

RefMonthBeginEnd
ABCDEF11112023-1100
ABCDEF11112023-1201
ABCDEF11112024-01172
ABCDEF11112024-027272
ABCDEF11112024-037272
ABCDEF11112024-047272
ABCDEF11112024-057272
ABCDEF11112024-067272
ABCDEF11112024-077272
ABCDEF11112024-087272
ABCDEF11112024-097272
ABCDEF11112024-107272
ABCDEF11112024-117272
ABCDEF11112024-127272
ABCDEF11112025-017272

补充规则:

  • 2023-12月的座位变动为1,因此该月期初值为0,期末值为1;
  • 2024-01月期初值为1(因47个座位的增加发生在1月2日),期末值为1+47+24=72;
  • 2024-03至2024-11月无操作,每月期初、期末值均为72;
  • 2024-12月期初值为72(12月22日新增72座次日取消),期末值仍为72;
  • 2025-01月期初、期末值均为72。
解决方案

实现思路

  1. 生成月份序列:构建覆盖目标时间范围的所有月份,避免遗漏;
  2. 计算月度变动:将座位变动记录映射到对应发生月份,统计每月总变动量;
  3. 计算期初/期末值:通过累计求和得到期末值,期初值取上月期末值,无变动时延续上月数值;
  4. 处理边界情况:初始月份期初值设为0,抵消类变动(如新增后取消)不改变期末值。

Snowflake SQL代码

WITH date_range AS (
    -- 生成2023-11至2025-01的所有月份
    SELECT
        'ABCDEF1111' AS ref,
        DATE_TRUNC('MONTH', DATEADD('MONTH', seq4(), '2023-11-01')) AS month_start
    FROM TABLE(GENERATOR(ROWCOUNT => 13)) -- 13个月:2023-11到2025-01
),
monthly_changes AS (
    -- 按月份聚合座位变动总和
    SELECT
        ref,
        DATE_TRUNC('MONTH', start_date) AS month_start,
        SUM(seat) AS total_change
    FROM your_table_name -- 替换为实际表名
    GROUP BY ref, DATE_TRUNC('MONTH', start_date)
),
combined_data AS (
    -- 关联月份序列与变动数据,无变动月份填充0
    SELECT
        dr.ref,
        TO_CHAR(dr.month_start, 'YYYY-MM') AS month,
        COALESCE(mc.total_change, 0) AS total_change
    FROM date_range dr
    LEFT JOIN monthly_changes mc
        ON dr.ref = mc.ref AND dr.month_start = mc.month_start
),
running_totals AS (
    -- 计算累计变动得到期末值,期初值取上月期末值
    SELECT
        ref,
        month,
        COALESCE(LAG(running_total) OVER (PARTITION BY ref ORDER BY month), 0) AS begin,
        running_total AS end
    FROM (
        SELECT
            ref,
            month,
            SUM(total_change) OVER (PARTITION BY ref ORDER BY month) AS running_total
        FROM combined_data
    ) t
)
SELECT * FROM running_totals ORDER BY month;

代码说明

  • date_range:用GENERATOR函数生成指定范围的月份序列,ROWCOUNT根据所需月份数调整;
  • monthly_changes:按月份聚合所有座位变动,确保同月变动求和;
  • combined_data:将月份序列与变动数据关联,无变动的月份变动量设为0;
  • running_totals:通过窗口函数SUM(...) OVER (...)计算累计变动得到期末值,用LAG函数获取上月期末值作为本月期初值;
  • 自动处理无变动月份的数值延续,以及变动抵消场景(如2024-12月+72与-72总和为0,期末值保持72)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 13:40:53