【问题标题】:Reduce field value based on previous value on row根据行上的先前值减少字段值
【发布时间】:2014-10-02 16:28:25
【问题描述】:

我有一张这样的桌子:

Order Number  ItemCode   Quantity_Ordered   AvailableInShop
-----------------------------------------------------------
1             10         3                  3
2             10         2                  3 

但我需要一个查询来获得这个输出:

Order Number  ItemCode   Quantity_Ordered   AvailableInShop
-----------------------------------------------------------
1             10         3                  3
2             10         2                  0

这是因为第一个销售订单已经占用了后续订单的所有数量。

这是我尝试过的

select 
  [order number], 
  itemcode, 
  quantity_ordered, 
  availableInshop, 
  Row_Number() over (partition itemcode order by [order number] asc) Rownumber  
from Orders

【问题讨论】:

  • 您的问题是什么?我们需要更多细节。
  • 欢迎来到 StackOverflow。这不是代码生成器服务。请与我们分享您尝试了什么,有什么问题,以及我们如何提供帮助。请付出一些努力来激发可能的帮助者(如果您不想这样做,请为编程付费)。请阅读How do I ask a good question? 文章了解更多信息。
  • 我在这里诚实的建议是不要将库存数据和订单数据存储在同一个表中。将项目和库存数据放在一个表中,将订单数据放在另一个表中。然后,每当下新订单时,更改库存表以反映新库存。这也让您无需注册“否定”订单即可增加可用数量。

标签: sql sql-server-2008 tsql


【解决方案1】:

感谢你给我最后的动力,如下所示;

DECLARE @Orders TABLE
            (
                DocEntry bigint,  DocDate datetime,  [Customer_Name] nvarchar(max),Itemcode nvarchar(50), [Order_Number] nvarchar(max)
                ,Quantity int, OnHand int ,RowNumber int
            );

            INSERT INTO @Orders
            select O.DocEntry,  o.DocDate,CardName,r.itemcode, o.NumAtCard [Order_Number], r.Quantity, 
            OnHand- (select sum(quantity) from rdr1 with (nolock)  where itemcode= r.itemcode and linestatus='o' and pickidNo is not null) OnHand
            , ROW_NUMBER() over (partition by r.itemcode 
                                                                                        order by o.docentry asc)
            from ORDR o join RDR1 r on o.DocEntry = r.DocEntry
            inner join OITW W with (nolock) on r.ItemCode=W.ItemCode and W.WhsCode=r.WhsCode  where 
          r.ItemCode ='1034356' and o.docstatus='o' and canceled='n' and r.pickidno is null
            order by 1          ;

             with mother as(  --cte produces unused_onhand
             select *, 

             case when (select top 1 OnHand -Quantity from @orders where RowNumber= r.RowNumber-1 and Itemcode=r.Itemcode )
             IS NUll 
             then r.OnHand --- for first row value append onHand
             else
             (select top 1 OnHand - ( select SUM(quantity ) from @Orders where Itemcode=r.Itemcode and RowNumber < r.RowNumber    ) from @orders where RowNumber= r.RowNumber-1 and Itemcode=r.Itemcode )
             end Unused_OnHand -- for subsequent onhand, append unused_onhand
             from @Orders r
             )  
             select *,           
             CASE when  (CAST( CAST( Unused_OnHand as  NUmeric(18,3)) / CAST( Quantity as  NUmeric(18,3) ) as NUmeric(18,3)) *100 ) > 100
                then CAST (100.00 AS numeric(18,3))

                when (CAST( CAST( Unused_OnHand as  NUmeric(18,3)) / CAST( Quantity as  NUmeric(18,3) ) as NUmeric(18,3)) *100 ) < 0
                then 0
                else
                (CAST( CAST( Unused_OnHand as  NUmeric(18,3)) / CAST( Quantity as  NUmeric(18,3) ) as NUmeric(18,3)) *100 ) 
                end[Fulfillment%] 
             from mother

【讨论】:

    【解决方案2】:

    假设我正确理解了您的问题,并且您拥有支持 LAG 和 FIRST_VALUE 函数的 SQL Server 版本,那么下面的 T-SQL 是一种可能的方式来做您想做的事情:

    with myCte as 
    (
        select o.oNum, o.itemCode, o.qOrdered, 
            sum(o.qOrdered) over (partition by o.itemCode order by o.oNum asc rows between unbounded preceding and current row) as totalOrdered,
            FIRST_VALUE(o.qAvailable) over (partition by o.itemCode order by o.oNum asc) as initialAvailability
        from dbo.Orders as o
    ),
    
    myCte2 as
    (
        select *, case when m.initialAvailability-m.totalOrdered < 0 then 0 else m.initialAvailability-m.totalOrdered end as nextAvailability
        from myCte as m
    ),
    
    myCte3 as
    (
        select *,
            lag(m.nextAvailability) over (partition by m.itemCode order by m.oNum asc) as prevAvailability
        from myCte2 as m
    )
    
    select m.oNum, m.itemCode, m.qOrdered, case when m.prevAvailability is null then m.initialAvailability else m.prevAvailability end as qAvailable
    from myCte3 as m
    

    当然,我同意其他人的观点,即不将可用性与订单数量存储在同一记录中将是一种更明智的长期方法。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-02-10
      • 2012-04-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-12-09
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多