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

如何基于优先级对stock表多行库存数量进行扣减计算?

这是个很常见的按优先级分配库存扣减的场景,用窗口函数就能干净利落地解决,我给你拆解下具体思路和代码:

核心思路

要实现按优先级依次扣减,关键是先算出每个仓库在优先级序列里的累计可用量,再根据这个累计值判断当前仓库需要承担多少扣减:

  • 先按SKU分组、优先级排序,计算从最高优先级到当前仓库的累计库存
  • 对比累计库存和需要扣减的总量,确定每个仓库的实际扣减数量
  • 最后用计算出的扣减量更新原表的库存
具体实现代码

假设我们要扣减的总量是4,下面以支持窗口函数的数据库(比如PostgreSQL、MySQL 8.0+、SQL Server等)为例:

通用版(PostgreSQL/SQL Server)

-- 定义要扣减的总量
DECLARE @deduct_qty INT = 4;

WITH stock_with_running_total AS (
    SELECT 
        Id, SKU, priority, Warehouse, Qty,
        -- 计算从最高优先级到当前行的累计库存
        SUM(Qty) OVER (PARTITION BY SKU ORDER BY priority) AS running_total,
        -- 计算当前行之前的累计库存(第一行用0替代NULL)
        COALESCE(SUM(Qty) OVER (PARTITION BY SKU ORDER BY priority ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING), 0) AS prev_running_total
    FROM stock
    -- 如果只处理特定SKU可以加WHERE SKU = 'sku1',否则处理所有SKU
),
deduct_calculation AS (
    SELECT 
        Id,
        CASE
            -- 累计库存还没到扣减量,全扣
            WHEN running_total <= @deduct_qty THEN Qty
            -- 前面的累计已经覆盖了扣减量,不扣
            WHEN prev_running_total >= @deduct_qty THEN 0
            -- 扣减剩余的部分
            ELSE @deduct_qty - prev_running_total
        END AS deduct_amount
    FROM stock_with_running_total
)
-- 更新原表库存
UPDATE stock s
SET Qty = s.Qty - dc.deduct_amount
FROM deduct_calculation dc
WHERE s.Id = dc.Id;

MySQL 适配版

MySQL的UPDATE JOIN语法略有不同,调整后的代码如下:

SET @deduct_qty = 4;

WITH stock_with_running_total AS (
    SELECT 
        Id, SKU, priority, Warehouse, Qty,
        SUM(Qty) OVER (PARTITION BY SKU ORDER BY priority) AS running_total,
        COALESCE(SUM(Qty) OVER (PARTITION BY SKU ORDER BY priority ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING), 0) AS prev_running_total
    FROM stock
    -- 可选:WHERE SKU = 'sku1'
),
deduct_calculation AS (
    SELECT 
        Id,
        CASE
            WHEN running_total <= @deduct_qty THEN Qty
            WHEN prev_running_total >= @deduct_qty THEN 0
            ELSE @deduct_qty - prev_running_total
        END AS deduct_amount
    FROM stock_with_running_total
)
UPDATE stock s
JOIN deduct_calculation dc ON s.Id = dc.Id
SET s.Qty = s.Qty - dc.deduct_amount;
代码逻辑解释

拿你的示例数据来说:

  1. running_total列计算结果分别是1、3、6(对应p1到p3的累计库存)
  2. prev_running_total列结果是0、1、3
  3. 扣减逻辑:
    • p1仓库:累计1≤4,全扣1,库存变为0
    • p2仓库:累计3≤4,全扣2,库存变为0
    • p3仓库:前面累计3<4,扣减4-3=1,库存从3变为2,完全符合你的预期输出

如果需要批量处理多个SKU的扣减,只需要去掉WHERE SKU = 'sku1',并且可以把固定的@deduct_qty改成关联一个扣减需求表(比如每个SKU对应不同的扣减量)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 08:52:02