使用 SQL 服务器的库存时效

Stock ageing with SQL Server

我有一个table内容如下,其中'ItemName'是物品的名称,'CurrentStock'是物品的当前库存数量,所有其他列都是物品的总和当年的进货和出货。现在我想用 0 替换所有负值,并以 FIFO 顺序用正值调整这些负值。谁能指导我如何在 SQL 服务器中做到这一点。

这是预期结果

最初我是这样尝试的

select ItemName,CurrentStock, 
case when (Qnty2018+Qnty2017+Qnty2016+Qnty2015+Qnty2014+Qnty2013)<0 and (Qnty2018+Qnty2017+Qnty2016+Qnty2015+Qnty2014+Qnty2013+Qnty2012andBefore)>=0 then (Qnty2018+Qnty2017+Qnty2016+Qnty2015+Qnty2014+Qnty2013+Qnty2012andBefore) 
    when (Qnty2017+Qnty2016+Qnty2015+Qnty2014+Qnty2013)<0 and (Qnty2017+Qnty2016+Qnty2015+Qnty2014+Qnty2013+Qnty2012andBefore)>=0 THEN (Qnty2017+Qnty2016+Qnty2015+Qnty2014+Qnty2013+Qnty2012andBefore)
    when (Qnty2016+Qnty2015+Qnty2014+Qnty2013)<0 and (Qnty2016+Qnty2015+Qnty2014+Qnty2013+Qnty2012andBefore)>=0 THEN (Qnty2016+Qnty2015+Qnty2014+Qnty2013+Qnty2012andBefore)
    when (Qnty2015+Qnty2014+Qnty2013)<0 and (Qnty2015+Qnty2014+Qnty2013+Qnty2012andBefore)>=0 THEN (Qnty2015+Qnty2014+Qnty2013+Qnty2012andBefore)
    when (Qnty2014+Qnty2013)<0 and (Qnty2014+Qnty2013+Qnty2012andBefore)>=0 THEN (Qnty2014+Qnty2013+Qnty2012andBefore)
    when Qnty2013 <0 and Qnty2013+Qnty2012andBefore >=0 then Qnty2013+Qnty2012andBefore 
else Qnty2012andBefore end as Qnty2012andBefore,
case when Qnty2013<0 then 0
    when (Qnty2018+Qnty2017+Qnty2016+Qnty2015+Qnty2014)<0 and (Qnty2018+Qnty2017+Qnty2016+Qnty2015+Qnty2014+Qnty2013)>=0 then (Qnty2018+Qnty2017+Qnty2016+Qnty2015+Qnty2014+Qnty2013) 
    when (Qnty2017+Qnty2016+Qnty2015+Qnty2014)<0 and (Qnty2017+Qnty2016+Qnty2015+Qnty2014+Qnty2013)>=0 THEN (Qnty2017+Qnty2016+Qnty2015+Qnty2014+Qnty2013)
    when (Qnty2016+Qnty2015+Qnty2014)<0 and (Qnty2016+Qnty2015+Qnty2014+Qnty2013)>=0 THEN (Qnty2016+Qnty2015+Qnty2014+Qnty2013)
    when (Qnty2015+Qnty2014)<0 and (Qnty2015+Qnty2014+Qnty2013)>=0 THEN (Qnty2015+Qnty2014+Qnty2013)
    when (Qnty2014)<0 and (Qnty2014+Qnty2013)>=0 THEN (Qnty2014+Qnty2013)
else Qnty2013 end as Qnty2013,
case when Qnty2014<0 then 0
    when (Qnty2018+Qnty2017+Qnty2016+Qnty2015)<0 and (Qnty2018+Qnty2017+Qnty2016+Qnty2015+Qnty2014)>=0 then (Qnty2018+Qnty2017+Qnty2016+Qnty2015+Qnty2014) 
    when (Qnty2017+Qnty2016+Qnty2015)<0 and (Qnty2017+Qnty2016+Qnty2015+Qnty2014)>=0 THEN (Qnty2017+Qnty2016+Qnty2015+Qnty2014)
    when (Qnty2016+Qnty2015)<0 and (Qnty2016+Qnty2015+Qnty2014)>=0 THEN (Qnty2016+Qnty2015+Qnty2014)
    when (Qnty2015)<0 and (Qnty2015+Qnty2014)>=0 THEN (Qnty2015+Qnty2014)
else Qnty2014 end as Qnty2014,
case when Qnty2015<0 then 0
    when (Qnty2018+Qnty2017+Qnty2016)<0 and (Qnty2018+Qnty2017+Qnty2016+Qnty2015)>=0 then (Qnty2018+Qnty2017+Qnty2016+Qnty2015) 
    when (Qnty2017+Qnty2016)<0 and (Qnty2017+Qnty2016+Qnty2015)>=0 THEN (Qnty2017+Qnty2016+Qnty2015)
    when (Qnty2016)<0 and (Qnty2016+Qnty2015)>=0 THEN (Qnty2016+Qnty2015)
else Qnty2015 end as Qnty2015,
    case when Qnty2016<0 then 0
    when (Qnty2018+Qnty2017)<0 and (Qnty2018+Qnty2017+Qnty2016)>=0 then (Qnty2018+Qnty2017+Qnty2016) 
    when (Qnty2017)<0 and (Qnty2017+Qnty2016)>=0 THEN ( Qnty2017+Qnty2016)
else Qnty2016 end as Qnty2016,
case when Qnty2017<0 then 0
    when (Qnty2018)< 0 and (Qnty2018+Qnty2017)>=0 then (Qnty2018+Qnty2017) 
else Qnty2017 end as Qnty2017,
case when Qnty2018<0 then 0 else Qnty2018 end as Qnty2018 FROM StockTable

但它给出了这样的错误输出

谢谢

您认为 CASE 中的总和有什么用?鉴于您的示例,在我看来,每个单独列上的 CASE 具有您想要的效果。为了计算 Qnty2012andBeforeCurrentStock 中减去,再次在被加数上单独应用 CASE。像那样:

SELECT ItemName,
       CurrentStock,
       CASE
         WHEN Qnty2018 < 0
           THEN 0
         ELSE
           Qnty2018
       END Qnty2018,
       ...
       CASE
         WHEN Qnty2013 < 0
           THEN 0
         ELSE
           Qnty2013
       END Qnty2013,
       CurrentStock
       -
       CASE
         WHEN Qnty2018 < 0
           THEN 0
         ELSE
           Qnty2018
       END
       ...
       -
       CASE
         WHEN Qnty2013 < 0
           THEN 0
         ELSE
           Qnty2013
       END Qnty2012andBefore
       FROM StockTable;

对此可能有两种解决方案。

  1. 使用#Temp table 如下图

    SELECT ItemName,CurrentStock,
    CASE when Qnty2018<0 THEN 0 ELSE Qnty2018 END as Qnty2018,
    CASE when Qnty2017<0 THEN 0 ELSE Qnty2017 END as Qnty2017,
    CASE when Qnty2016<0 THEN 0 ELSE Qnty2016 END as Qnty2016,
    CASE when Qnty2015<0 THEN 0 ELSE Qnty2015 END as Qnty2015,
    CASE when Qnty2014<0 THEN 0 ELSE Qnty2014 END as Qnty2014,
    CASE when Qnty2013<0 THEN 0 ELSE Qnty2013 END as Qnty2013,
    CASE when Qnty2012andBefore<0 THEN 0 ELSE Qnty2012andBefore END as Qnty2012andBefore INTO #Temp FROM StockTable
    
    update #Temp set Qnty2018=CurrentStock WHERE Qnty2018<>0 AND Qnty2017=0 AND Qnty2016=0 AND Qnty2015=0 AND Qnty2014=0 AND Qnty2013=0 AND Qnty2012andBefore=0
    update #Temp set Qnty2017=CurrentStock-Qnty2018 WHERE Qnty2017<>0 AND Qnty2016=0 AND Qnty2015=0 AND Qnty2014=0 AND Qnty2013=0 AND Qnty2012andBefore=0
    update #Temp set Qnty2016=CurrentStock-Qnty2018+Qnty2017 WHERE Qnty2016<>0 AND Qnty2015=0 AND Qnty2014=0 AND Qnty2013=0 AND Qnty2012andBefore=0
    update #Temp set Qnty2015=CurrentStock-Qnty2018+Qnty2017+Qnty2016 WHERE Qnty2015<>0 AND Qnty2014=0 AND Qnty2013=0 AND Qnty2012andBefore=0
    update #Temp set Qnty2014=CurrentStock-Qnty2018+Qnty2017+Qnty2016+Qnty2015 WHERE Qnty2014<>0 AND Qnty2013=0 AND Qnty2012andBefore=0
    update #Temp set Qnty2013=CurrentStock-Qnty2018+Qnty2017+Qnty2016+Qnty2015+Qnty2014 WHERE Qnty2013<>0 AND Qnty2012andBefore=0
    update #Temp set Qnty2012andBefore=CurrentStock-Qnty2018+Qnty2017+Qnty2016+Qnty2015+Qnty2014+Qnty2013 WHERE Qnty2012andBefore<>0
    SELECT * FROM #Temp
    

    2.Using Cursor,你可以在行的基础上迭代并编写逻辑。因为在 SQL 中不推荐这样做,所以只有在没有其他选择时才使用它。