简体   繁体   English

SQL Sum over partition

[英]SQL Sum over partition

I have 6000 pieces of a stock item and the stock is split into 2 batches containing 4000 pieces and 2000 pieces. 我有6000件库存产品,库存分为2批,包含4000件和2000件。

Based on sales orders I am trying to predict which batch of stock will fulfil each order. 根据销售订单,我试图预测哪批库存将满足每个订单。

For example: 例如:

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

This produces this table: 这会产生这个表:

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

Then I have another query for example: 然后我有另一个查询例如:

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

This would produce a table like this: 这会生成一个这样的表:

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

So using these two tables I'd like to predict which batch of stock order would pick from. 因此,使用这两个表格,我想预测哪一批股票订单会从中挑选。 The stock is using a FIFO system, so based on the table it would have to fulfil the orders using the batch code 987ZYX batch first. 库存正在使用FIFO系统,因此根据表格,它必须首先使用批次代码987ZYX批次来完成订单。 I'm looking for a query that produces this as a table: 我正在寻找一个产生这个表的查询:

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

I have selected the batches above based on the required date, for example the first order that is required is 1/7/18 so that would remove 300 pieces from batch 987ZYX, then I continued in this method until I had to fulfil the order from the next batch 我根据所需的日期选择了上面的批次,例如所需的第一个订单是1/7/18,这样就可以从批次987ZYX中删除300件,然后我继续这个方法,直到我必须完成订单来自下一批

I understand I could use the SUM over method, but how could I use this to make sure it doesn't use more stock than is available in the batch, as you can see above I'd like to display two batches if possible if it will need to fulfil from two. 我知道我可以使用SUM over方法,但是如何使用它来确保它不会使用比批处理中更多的库存,正如您在上面所看到的,如果可能的话,我想显示两个批次将需要满足两个。

First, I hate dates (partially cause my birthday is on February 29, partially because my 'd' key is not working properly), so I created index for each order and each batch, and I assume that orders should be processed in the increasing order of the index from minimum possible batch index. 首先,我讨厌日期(部分原因是我的生日是在2月29日,部分是因为我的'd'键不能正常工作),所以我为每个订单和每个批次创建了索引,我假设订单应该在增加中处理最小可能批次索引的索引顺序。 I also don't check if the items are in stock at the time of the order, as well as many other things. 我也不会在订单时检查物品是否有库存,以及许多其他东西。

As @GordonLinoff suggested, we will use cumulative sums. 正如@GordonLinoff建议的那样,我们将使用累计金额。 I create new tables with cumulative quantity for tables #orders and #batch (we just sum up all quantity from orders/batches with id up to current). 我为表#orders和#batch创建了具有累积数量的新表(我们只是将订单/批次的所有数量总结为id到当前)。 And then we recursively calculate the batch that ... well, we somehow find the necessary batch. 然后我们递归计算批次......好吧,我们以某种方式找到必要的批次。 I guess we don't need recursion, but I just learnt how to use it in SQL, so I'm proud to use it in unnecessary places. 我想我们不需要递归,但我刚学会了如何在SQL中使用它,所以我很自豪能在不必要的地方使用它。 Oh, and I also forgot to check if the product from batch and orders is the same... 哦,我也忘了检查批次和订单中的产品是否相同......

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

EDIT: I corrected the major issues (separated calculations for each product, eliminated stupid recursion) except the datetime being changed to id. 编辑:我纠正了主要问题(每个产品的分开计算,消除了愚蠢的递归),但日期时间被更改为id。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM