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

如何使用Presto SQL查询含结转库存的各商品每日最高库存数

Presto SQL 实现带库存结转的每日最高库存统计

需求核心说明

我们需要统计每个商品每日的最高库存,规则为:

  • 当日有库存变动记录时,取「当日所有库存记录的最大值」和「前一日结转的库存值」两者的较大值
  • 当日无库存变动记录时,最高库存直接等于前一日结转的库存值

完整实现SQL

WITH 
-- 步骤1:基础聚合,计算每个商品每日的最大库存、日终库存
daily_agg AS (
    SELECT 
        date_format(from_unixtime(CAST(update_timestamp AS BIGINT)/1000), '%Y-%m-%d') AS day,
        item_id,
        MAX(units) AS daily_max_units,
        -- 用MAX_BY取当日最后一笔时间戳对应的库存,即当日结转至次日的库存
        MAX_BY(units, update_timestamp) AS daily_end_units
    FROM your_table_name -- 替换为你的实际表名
    GROUP BY item_id, date_format(from_unixtime(CAST(update_timestamp AS BIGINT)/1000), '%Y-%m-%d')
),
-- 步骤2:生成业务时间范围内的连续日期序列
date_range AS (
    SELECT 
        date_format(day_seq, '%Y-%m-%d') AS day
    FROM (
        SELECT UNNEST(SEQUENCE(
            -- 时间范围可以根据业务需要自定义,这里默认取表中最早到最晚的事务日期
            (SELECT MIN(date(from_unixtime(CAST(update_timestamp AS BIGINT)/1000))) FROM your_table_name),
            (SELECT MAX(date(from_unixtime(CAST(update_timestamp AS BIGINT)/1000))) FROM your_table_name),
            INTERVAL '1' DAY
        )) AS day_seq
    )
),
-- 步骤3:生成每个商品对应的全量日期序列,补全无事务的空日期
item_full_dates AS (
    SELECT 
        dr.day,
        i.item_id
    FROM date_range dr
    CROSS JOIN (SELECT DISTINCT item_id FROM your_table_name) i
),
-- 步骤4:关联聚合数据,用窗口函数填充结转值
joined_data AS (
    SELECT 
        ifd.day,
        ifd.item_id,
        da.daily_max_units,
        da.daily_end_units,
        -- 前向填充最近的非空日终库存,作为当日的结转基础
        LAST_VALUE(da.daily_end_units IGNORE NULLS) OVER (
            PARTITION BY ifd.item_id 
            ORDER BY ifd.day 
            ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
        ) AS carry_over_end_units,
        -- 取上一日的结转库存,用于和当日最大值比较
        LAG(LAST_VALUE(da.daily_end_units IGNORE NULLS) OVER (
            PARTITION BY ifd.item_id 
            ORDER BY ifd.day 
            ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
        ), 1) OVER (PARTITION BY ifd.item_id ORDER BY ifd.day) AS prev_day_carry_over
    FROM item_full_dates ifd
    LEFT JOIN daily_agg da ON ifd.day = da.day AND ifd.item_id = da.item_id
)
-- 最终计算每日最高库存
SELECT 
    day,
    item_id,
    COALESCE(GREATEST(daily_max_units, prev_day_carry_over), daily_max_units, carry_over_end_units) AS max_units
FROM joined_data
ORDER BY item_id, day

兼容说明

如果你的Presto版本不支持MAX_BY函数,可以将daily_agg部分替换为以下ROW_NUMBER实现:

daily_agg AS (
    WITH daily_rn AS (
        SELECT 
            date_format(from_unixtime(CAST(update_timestamp AS BIGINT)/1000), '%Y-%m-%d') AS day,
            item_id,
            units,
            ROW_NUMBER() OVER (PARTITION BY item_id, date_format(from_unixtime(CAST(update_timestamp AS BIGINT)/1000), '%Y-%m-%d') ORDER BY update_timestamp DESC) AS rn
        FROM your_table_name
    )
    SELECT 
        day,
        item_id,
        MAX(units) AS daily_max_units,
        MAX(CASE WHEN rn = 1 THEN units END) AS daily_end_units
    FROM daily_rn
    GROUP BY item_id, day
)

效果验证

以你给出的示例为例:

  • item1 2021-11-24的日终库存为6,2021-11-25无事务,当日最高库存取结转值6
  • item1 2021-11-26的当日最大库存为4,和前一日结转值6取较大值,最终最高库存为6,完全符合需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 18:06:09