Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/26.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 拆分数量以完成订单-基于集合的查询_Sql_Sql Server_Database - Fatal编程技术网

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问题是什么?你试过什么?请更详细地解释您的问题。问题是,在我的帖子解决方案中,从前两个表中获取第三个表的基于集合的方法是什么?我可以用一种基于游标的迭代方法来解决这个问题,但我想知道是否可以用窗口函数来实现。订单和容器之间的关系是什么?在示例表中,订单1与容器1-10匹配,但订单2仅与容器10-12匹配。如何确定?运行字段来自何处?容器只是包含供应商提供的原始产品的盒子。这是我的存货。一旦我收到订单,我需要获取最旧的可用容器,并使用它来完成订单。如果该容器中剩余的数量不足以完成订单,那么我需要取下一个最旧的,因此直到订单完全完成。这几乎是我到目前为止所想到的,但它无法浸入容器10中以满足订单1。@GoatCO。我很肯定会的。仔细检查你的oc等价物的连接条件。嗨,戈登,非常感谢。我想这不起作用,因为我已经纠正了一些打字错误。此外,OrderContainerAmount为每行生成0。我在想为什么会这样。一旦我得到它,我会将你的答案标记为正确。我认为你需要一个开放的时间间隔加入,否则当一个包被一个订单完全填满时,它仍然会包含在下一个订单中。工作就像一个符咒!谢谢嗨,安安,你能推荐一本关于这类问题的书吗?我看到你在文章的一部分用了斜体字,我想这是引用了其他文字?我真正的问题比这更复杂,所以我想读一些类似的问题。谢谢,这不是一句话。那是我的原创作品。我不知道有哪本书能解决这类问题。