Sql 拆分数量以完成订单-基于集合的查询
我试图找到一种基于集合的方法来执行以下操作: 我的仓库里只有一种产品。这个产品有不同尺寸的盒子。我必须使用我的库存完成订单,根据需要拆分集装箱以达到准确的订单数量。订单和库存项目都必须采用先进先出的方式进行处理 作为一个例子,这里有一些值和手工计算的解决方案Sql 拆分数量以完成订单-基于集合的查询,sql,sql-server,database,Sql,Sql Server,Database,我试图找到一种基于集合的方法来执行以下操作: 我的仓库里只有一种产品。这个产品有不同尺寸的盒子。我必须使用我的库存完成订单,根据需要拆分集装箱以达到准确的订单数量。订单和库存项目都必须采用先进先出的方式进行处理 作为一个例子,这里有一些值和手工计算的解决方案 +---------+-------+ +-----------+-------+ | OrderId | OQtty | | Container | CQtty | +---------+-------+ +-----------+
+---------+-------+ +-----------+-------+
| OrderId | OQtty | | Container | CQtty |
+---------+-------+ +-----------+-------+
| 1 | 87000 | | 1 | 10000 |
| 2 | 26500 | | 2 | 10000 |
| 3 | 12000 | | 3 | 10000 |
| 4 | 43600 | | 4 | 10000 |
| 5 | 3000 | | 5 | 10000 |
| | | | 6 | 5000 |
| | | | 7 | 10000 |
| | | | 8 | 10000 |
| | | | 9 | 10000 |
| | | | 10 | 10000 |
| | | | 11 | 10000 |
| | | | 12 | 10000 |
| | | | 13 | 10000 |
| | | | 14 | 2500 |
| | | | 15 | 2500 |
| | | | 16 | 10000 |
| | | | 17 | 10000 |
| | | | 18 | 10000 |
| | | | 19 | 10000 |
| | | | 20 | 10000 |
+---------+-------+ +-----------+-------+
+---------+-----------+-------+---------+
| OrderId | Container | CQtty | Running |
+---------+-----------+-------+---------+
| 1 | 1 | 10000 | 10000 |
| 1 | 2 | 10000 | 20000 |
| 1 | 3 | 10000 | 30000 |
| 1 | 4 | 10000 | 40000 |
| 1 | 5 | 10000 | 50000 |
| 1 | 6 | 5000 | 55000 |
| 1 | 7 | 10000 | 65000 |
| 1 | 8 | 10000 | 75000 |
| 1 | 9 | 10000 | 85000 |
| 1 | 10 | 2000 | 87000 |
| 2 | 10 | 8000 | 8000 |
| 2 | 11 | 10000 | 18000 |
| 2 | 12 | 8500 | 26500 |
| 3 | 12 | 1500 | 1500 |
| 3 | 13 | 10000 | 11500 |
| 3 | 14 | 500 | 12000 |
| 4 | 14 | 2000 | 2000 |
| 4 | 15 | 2500 | 4500 |
| 4 | 16 | 10000 | 14500 |
| 4 | 17 | 10000 | 24500 |
| 4 | 18 | 10000 | 34500 |
| 4 | 19 | 9100 | 43600 |
| 5 | 19 | 900 | 900 |
| 5 | 20 | 2100 | 3000 |
+---------+-----------+-------+---------+
编辑:我忘了提到这是green field sql server 2012。谢谢这可以通过使用窗口函数来完成,但这有点棘手。之所以可以这样做,是因为你正在计算总量。在您的示例中,容器8的一部分转到订单1,另一部分转到订单2。信不信由你,这比将集装箱8的一部分转到订单1要容易得多。剩下的都浪费了 这个想法很简单。对集装箱和订单进行累计合计。然后使用非等联接查找用于每个订单的容器-这是累积和重叠的地方。然后再做一些欺骗来处理边界。以下是如何做到这一点的想法:
with oq as (
select o.*,
sum(oqty) over (order by orderid) - oqty as sumoqty_start,
sum(oqty) over (order by orderid) as sumoqty_end
from orders o
),
cq as (
select c.*,
sum(cqty) over (order by container) - cty as sumcqty_start,
sum(cqty) over (order by container) as sumcqty_end
from contains c
),
oc as (
select o.orderid, o.sumoqty_start, o.sumoqty_end,
c.container, c.sumcqty_start, c.sumcty_end
from oq join
cq
on oc.sumoqty_start < sumcqty_end and
oc.sumoqty_end > sumcqty_start
)
select o.orderid, c.containerid,
((case when sumcqty_end < sumoqty_end then sumcqty_end else sumoqty_end end) -
(case when sumcqty_start > sumoqty_start then sumcqty_start else sumoqty_start end)
) as OrderContainerAmount
from oc
order by 1, 2;
我认为这是正确的。如果没有SQL小提琴,我就无法测试它
WITH
O AS (SELECT *,SUM(OQtty) OVER(ORDER BY OrderId) Ort FROM @Orders),
C AS (SELECT *,SUM(CQtty) OVER(ORDER BY Container) Crt FROM @Containers)
SELECT
OrderId, Container, CQtty,
CASE WHEN Crt < Ort THEN Crt-Ort+OQtty ELSE Oqtty END AS Running
FROM O
INNER JOIN C ON Crt > Ort-OQtty AND Crt < Ort+CQtty
ORDER BY OrderId, Container
演示:
这是一个分区对齐问题。这与试图将北美和南美国家与欧洲和非洲国家相匹配是同一类型的问题,因为欧洲和非洲国家的大西洋海岸线彼此直接东西相接。解决方案应该是不可知哪个群体实际上是东方,哪个群体实际上是西方。所需要的只是这一逻辑:
如果两个国家南部极端纬度之间的差异小于任一国家的纬度“高度”,则它们重叠
同样,在这个问题中,“容器”和“订单”是完全可互换的。唯一重要的是运行总数之间的差异。如果ABSCrt-Ort