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

如何通过SQL按指定批次扣减商品库存?现有SQL执行异常求助

需求说明

现有ProductIn表中,Barcode为11的Coke有两条库存记录:

  • 入库日期2024-01-01、过期日期2025-03-10,库存数量20
  • 入库日期2024-02-06、过期日期2026-01-05,库存数量50

需要实现先进先出的扣减逻辑:从第一条记录扣减20(剩余0),第二条记录扣减5(剩余45),总计扣减25。

错误SQL的问题

当前执行的错误SQL会给所有Barcode=11的记录统一扣减25,导致第一条记录数量变为-5,第二条变为25,完全不符合需求。
错误SQL:

update ProductIn
set Quantity=Quantity-25
where Barcode=11    
正确的SQL实现

核心逻辑是按入库时间排序,依次扣减直到满足总扣减量25,以下是不同数据库环境下的实现方案:

方案1:MySQL 8.0+(支持窗口函数与CTE)

通过CTE计算每条记录的应扣减数量,再执行更新:

WITH inventory AS (
    SELECT 
        *,
        SUM(Quantity) OVER (ORDER BY InDate) AS cumulative_qty,
        25 AS total_deduct
    FROM ProductIn
    WHERE Barcode = 11
    ORDER BY InDate
),
deduct_calc AS (
    SELECT
        *,
        CASE
            WHEN cumulative_qty - Quantity < total_deduct THEN Quantity
            ELSE total_deduct - (cumulative_qty - Quantity)
        END AS deduct_amount
    FROM inventory
    WHERE cumulative_qty - Quantity < total_deduct
)
UPDATE ProductIn pi
JOIN deduct_calc dc ON pi.id = dc.id -- 假设表存在唯一主键id
SET pi.Quantity = pi.Quantity - dc.deduct_amount;

方案2:SQL Server

利用CTE计算扣减量后执行更新:

WITH inventory AS (
    SELECT 
        *,
        SUM(Quantity) OVER (ORDER BY InDate ROWS UNBOUNDED PRECEDING) AS cumulative_qty
    FROM ProductIn
    WHERE Barcode = 11
),
deduct_calc AS (
    SELECT
        *,
        CASE
            WHEN cumulative_qty - Quantity < 25 THEN Quantity
            ELSE 25 - (cumulative_qty - Quantity)
        END AS deduct_amount
    FROM inventory
    WHERE cumulative_qty - Quantity < 25
)
UPDATE pi
SET pi.Quantity = pi.Quantity - dc.deduct_amount
FROM ProductIn pi
JOIN deduct_calc dc ON pi.id = dc.id;

方案3:通用分步更新(适配无窗口函数的数据库)

如果数据库不支持窗口函数,可分两次原子更新:

  1. 扣减第一条记录的全部20:
-- MySQL用LIMIT,SQL Server用TOP 1,PostgreSQL用LIMIT 1
UPDATE ProductIn
SET Quantity = Quantity - 20
WHERE Barcode = 11
ORDER BY InDate
LIMIT 1;
  1. 从第二条记录扣减剩余的5:
UPDATE ProductIn
SET Quantity = Quantity - 5
WHERE Barcode = 11
AND Quantity > 0
ORDER BY InDate
LIMIT 1;

注意:需将两次更新放在同一事务中,避免中途异常导致数据不一致。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 08:13:09