如何解决T-SQL,仓库原理,两个数据集使用FIFO
我想使用 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 |
预期数据描述:
- Row ID = 1 --> 2022-01-01 我买了 1000 支铅笔,几个小时后卖出了 1000 支铅笔。
- 行 ID = 2 和 3 --> 2022-02-02 我购买了 2000 支铅笔,并向客户编号 1 (ID = 2) 出售了 1200 支铅笔,向客户编号 2 (ID = 3) 出售了 800 支铅笔。
- 行 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?
解决方法
合并买卖数据并计算累计“存货数量”:
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
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。