SQL总和

时间:2018-06-29 15:15:53

标签: sql sql-server sql-server-2008 tsql

我有6000件库存商品,库存分为2批,分别包含4000件和2000件。

基于销售订单,我试图预测将满足每个订单的那批库存。

例如:

SELECT product, order_qty, price, date_required FROM orders Where product = 'X'

这将产生此表:

product | order_qty | price |  date_required
------------------------------------------------------
 X      | 300       | 1.01  |   01/07/2018
 X      | 500       | 1.00  |   03/07/2018
 X      | 700       | 1.05  |   02/07/2018
 X      | 1000      | 1.00  |   01/08/2018
 X      | 2000      | 1.00  |   20/07/2018
 X      | 600       | 1.06  |   10/07/2018
 X      | 500       | 1.10  |   11/07/2018
 X      | 400       | 1.00  |   10/08/2018

然后我有另一个查询,例如:

SELECT batch, product, qty, date_received FROM batches where product = 'X'

这将产生一个像这样的表:

 batch  |product| qty   |  date_received
-------------------------------------------
 ABC123 | X     | 2000  |   01/04/2018
 987ZYX | X     | 4000  |   01/01/2018

因此,我想使用这两张表来预测将从哪一批库存订单中选择。库存使用的是FIFO系统,因此根据表格,必须首先使用批次代码987ZYX批次执行订单。我正在寻找将其生成为表格的查询:

product | order_qty | price |  date_required|   batch
------------------------------------------------------------------
 X      | 300       | 1.01  |   01/07/2018  |   987ZYX
 X      | 500       | 1.00  |   03/07/2018  |   987ZYX  
 X      | 700       | 1.05  |   02/07/2018  |   987ZYX
 X      | 1000      | 1.00  |   01/08/2018  |   ABC123
 X      | 2000      | 1.00  |   20/07/2018  |   987ZYX & ABC123
 X      | 600       | 1.06  |   10/07/2018  |   987ZYX
 X      | 500       | 1.10  |   11/07/2018  |   987ZYX
 X      | 400       | 1.00  |   10/08/2018  |   ABC123

我已根据所需日期选择了上述批次,例如,所需的第一笔订单是1/7/18,以便从987ZYX批次中删除300件,然后继续执行此方法,直到必须履行下一批的订单

我知道我可以使用SUM over方法,但是如何使用它来确保它使用的批次中的库存不超过该批次中的可用库存量,如您在上面看到的那样,如果要显示两个批次,如果需要从两个中实现,则可能会出现。

1 个答案:

答案 0 :(得分:1)

首先,我讨厌日期(部分原因是我的生日是2月29日,部分原因是我的'd'键无法正常工作),因此我为每个订单和每个批次创建了索引,并且我认为应该处理订单从最小的批处理索引开始,以索引的升序排列。我也不会检查订购时这些物品是否有库存,以及其他很多东西。

如@GordonLinoff所建议,我们将使用累积和。我为表#orders和#batch创建了具有累积数量的新表(我们只对ID / id为当前的订单/批次的所有数量进行求和)。然后,我们递归地计算出这样的批次...好吧,我们以某种方式找到了必要的批次。我猜我们不需要递归,但是我刚刚学习了如何在SQL中使用它,因此我很自豪在不必要的地方使用它。哦,我也忘记检查批次和订单中的产品是否相同...

drop table if exists #orders, #batch, #orders_cumulative, #batch_cumulative

create table #orders (id int, product varchar(10), order_qty int, price float, date_required date)
insert into #orders VALUES
(1, 'x', 300, 1.01, '20180107'),
(2, 'y', 500, 1, '20180307'),
(3, 'x', 700, 1.05, '20180207'),
(4, 'x', 1000, 1, '20180108'),
(5, 'x', 2000, 1, '20180402'),
(6, 'x', 600, 1.06, '20180302'),
(7, 'y', 100, 1, '20180203'),
(8, 'x', 100, 1, '20180402')

create table #batch (id int, batch varchar(10), product varchar(10), qty int)
insert into #batch VALUES
(1, 'abc', 'x', 1000),
(2, 'zxc', 'x', 1000),
(3, 'sd', 'x', 2000),
(4, 'eiso', 'y', 10000)

SELECT  o.*
        ,(select sum(order_qty) from #orders where id <= o.id and product = o.product) cumulative_qty
INTO    #orders_cumulative
from    #orders o

select  b.*
        ,isnull((select sum(qty) from #batch where id < b.id and product = b.product), 0) cumulative_ex_qty
        ,(select sum(qty) from #batch where id <= b.id and product = b.product) cumulative_qty
into    #batch_cumulative
FROM    #batch b

select top 10 * from #orders_cumulative
select top 10 * from #batch_cumulative

select  oc.*
        ,case when bc.cumulative_ex_qty > oc.cumulative_qty - oc.order_qty then convert(varchar(10), isnull(b1.batch, '') + ', ' + b2.batch) else b2.batch end batch
from    #orders_cumulative oc 
join    #batch_cumulative bc on oc.cumulative_qty between bc.cumulative_ex_qty and bc.cumulative_qty and oc.product = bc.product
join    #batch b2 on b2.id = bc.id 
left JOIN   #batch b1 on b1.id = bc.id - 1

编辑:我纠正了主要问题(每种产品的单独计算,消除了愚蠢的递归),但日期时间已更改为id。