0

我想使用 FIFO 组合两个数据集之间的数据。我认为仓库原理是一个很好的例子来解释我需要什么。

购买表:

ID_BUY 日期 物品 数数
39 2022-01-01 00:00 铅笔 1000
41 2022-02-02 00:00 铅笔 2000
44 2022-03-03 10:00 铅笔 3000
45 2022-03-03 12:00 铅笔 3500
47 2022-04-04 00:00 铅笔 4000
51 2022-05-05 00:00 胶水 5000
53 2022-06-06 00:00 6000

卖出表:

ID_SELL 日期 物品 数数
40 2022-01-01 16:00 铅笔 1000
42 2022-02-02 17:00 铅笔 1200
43 2022-02-02 18:00 铅笔 800
46 2022-03-03 14:00 铅笔 6500
48 2022-04-04 15:00 铅笔 2100
49 2022-04-04 16:00 铅笔 1100
52 2022-05-05 20:00 胶水 2000

预期数据:

ID ID_BUY ID_SELL 数数
1 39 40 1000
2 41 42 1200
3 41 43 800
4 44 46 3000
5 45 46 3500
6 47 48 2100
7 47 49 1100
8 51 52 2000

预期数据说明:

  • 行 ID = 1 --> 2022-01-01 我买了 1000 支铅笔,几小时后卖出了 1000 支铅笔。
  • 行 ID = 2 和 3 --> 2022-02-02 我买了 2000 支铅笔,将 1200 支铅笔卖给了 1 号客户(ID = 2),将 800 支铅笔卖给了 2 号客户(ID = 3)。
  • 行 ID = 4 和 5 --> 2022-03-03 我在两次交易(3000 和 3500)中购买了 6500 支铅笔,并在一次交易(6500)中出售了它们。在这种情况下,连续限制由买入交易决定。
  • 行 ID = 6 和 7 --> 2022-04-04 我在两次交易 (2100 + 1100) 中购买了 4000 支铅笔并卖出了 3200 支。现在我有 800 支铅笔(4000 - 3200 = 800)库存,等待下一次交易。在这种情况下,连续限制由卖出交易决定。
  • 预期数据中没有书籍,因为它们没有售出。

我试图用基于“销售表”的游标来解决这个问题。当我这样做时,我注意到我必须在光标内使用光标。第二个游标必须基于“BUY 表”加上未从预期数据表中解决的内容,并且在接下来的步骤中我将不得不使用 IF。也许有更简单的方法来解决这个问题?CTE?

4

1 回答 1

0

结合买入 + 卖出数据并计算累积的“库存数量”:

if object_id('tempdb..#tmp_fifo_count') is not null drop table #tmp_fifo_count
select
   b.ID_BUY,
   s.ID_SELL,
   (b.BuyedCummulativeCount - s.SoldCummulativeCount) as CountInStock,
   row_number() over(partition by b.ID_BUY order by s.[Date] asc) as RN, -- flag first sold over limit
   case
      when (b.BuyedCummulativeCount - s.SoldCummulativeCount) < 0 and b.BuyedCummulativeCount >= s.[Count]
        then (b.BuyedCummulativeCount - s.SoldCummulativeCount) -- correction to case over limit (for n:m relationship)
      else 0
   end +
   case
      when b.[Count] >= s.[Count] then s.[Count]    -- i have more in stock then i sold
      else b.[Count]                                -- i cannot sell over limit
   end as [Count]
into #tmp_fifo_count
from (
   select *, (select sum([Count]) from #tmp_buy b2 where b2.[Date] <= b0.[Date]) as BuyedCummulativeCount
   from #tmp_buy b0) as b
left join (
   select *, (select sum([Count]) from #tmp_sell s2 where s2.[Date] <= s0.[Date]) as SoldCummulativeCount
   from #tmp_sell s0) as s
on b.[Date] <= s.[Date]

得到结果:

-- output
select
   row_number() over(order by ID_BUY, ID_SELL) as ID,
   ID_BUY, 
   ID_SELL, 
   [Count] 
   --case when CountInStock >= 0 then CountInStock else 0 end as CountInStock
from #tmp_fifo_count
where (CountInStock >= 0 or RN = 1) -- Fully covered by one buy or not Fully covered by one buy
   and ID_SELL is not null          -- they were sold
于 2021-07-23T23:50:33.403 回答