【问题标题】:Allocate number of items in one table to available space in another将一个表中的项目数分配给另一个表中的可用空间
【发布时间】:2017-09-07 20:02:27
【问题描述】:

我有两张桌子:

#shelves(id INT, shelve_size INT);
id shelve_size
1   5
2   19
3   64
4   9

#palettes(id INT, number_of_items INT)
id number_of_items
1   3
2   9
3   32

我需要一个显示类似这样的查询,而不使用 while 循环:

id shelve_size number_of_items used available
1  5           3               3    2
1  5           9               2    0
2  19          9               7    12
2  19          32              12   0 
3  64          32              20   44      
4  9           0               0    9 <- not necesary row

它按 Id 顺序打开调色板并按 id 顺序将它们存储在货架上。如果在打开一个调色板包装后货架未满,则下一个将使用任何剩余容量。

第一个货架尺寸的容量为 5,因此从第一个托盘中取出 3 件物品,从第二个托盘取出 2 件物品。剩下的 7 件货盘 2 存放在货架 2 上。之后货架 2 有 20 件物品的空间。以此类推。

【问题讨论】:

  • 这没有任何意义......一张桌子和另一张桌子之间是什么关系......你能详细说明一下吗?
  • 不仅没有意义,而且这不是一个“免费为我工作”的网站。显示您尝试过的代码。
  • 要加入它们的表之间没有关系。
  • 对我来说很有意义。第一个货架尺寸的容量为 5,因此从第二个表的第一行获取 3,从第二行获取 2。这样一来,第一个货架就满了,第二个货架还有 7 个要分配。
  • 好吧,也许可以使用 SUM OVER PARTITION 和 LAG 的组合来实现这一点,但可能需要很长时间才能弄清楚!

标签: sql sql-server tsql sql-server-2016


【解决方案1】:

让我们从一个简单的例子开始。有 4 个架子 S1、S2、S3、S4 - 都有 5 件物品的空间。

还有三个托盘 P1(3 个单位)、P2(13 个单位)和 P3(3 个单位)。

很容易想象,最后的结果将是如下所示的货架。

+----+--------+--------+--------+--------+--------+
|    | Slot 1 | Slot 2 | Slot 3 | Slot 4 | Slot 5 |
+----+--------+--------+--------+--------+--------+
| S1 | P1     | P1     | P1     | P2     | P2     |
| S2 | P2     | P2     | P2     | P2     | P2     |
| S3 | P2     | P2     | P2     | P2     | P2     |
| S4 | P2     | P3     | P3     | P3     |        |
+----+--------+--------+--------+--------+--------+

为了在 SQL 中执行此操作,我在两个表中添加了几个运行总计列。

货架

+----------+------+---------------------+---------------------+
| shelf_id | size | cume size exclusive | cume size inclusive |
+----------+------+---------------------+---------------------+
| S1       |    5 |                   0 |                   5 |
| S2       |    5 |                   5 |                  10 |
| S3       |    5 |                  10 |                  15 |
| S4       |    5 |                  15 |                  20 |
+----------+------+---------------------+---------------------+

托盘

+------------+------------+---------------------------+---------------------------+
| pallet_id  | item count | cume item count exclusive | cume item count inclusive |
+------------+------------+---------------------------+---------------------------+
| P1         |          3 |                         0 |                         3 |
| P2         |         13 |                         3 |                        16 |
| P3         |          3 |                        16 |                        19 |
+------------+------------+---------------------------+---------------------------+

如果

,托盘将(至少部分)放在货架上
  • 搁板有空间放置它 - 即搁板(以及之前所有搁板)的容量大于之前所有调色板已使用的空间。 cume size inclusive &gt; cume item count exclusive
  • 托盘尚未完全拆包。 - 即所有先前货架的容量小于拆开所有托盘(包括当前托盘)所需的空间。 cume size exclusive &lt; cume item count inclusive

available 可以很容易地计算出来,方法是在托盘完全打开包装后查看货架是否已满,如果是则返回 0,否则返回 cume_size_inclusive - cume_item_count_inclusive

used 的计算方法是查看托盘物品数量并减去存储在之前或之后货架上的物品。

应该这样做。 Demo

WITH S
     AS (SELECT *,
                SUM(size) OVER (ORDER BY shelf_id ROWS UNBOUNDED PRECEDING) - size AS cume_shelf_capacity_exclusive,
                SUM(size) OVER (ORDER BY shelf_id ROWS UNBOUNDED PRECEDING)        AS cume_shelf_capacity_inclusive
         FROM   #shelves),
     P
     AS (SELECT *,
                SUM(item_count) OVER (ORDER BY pallet_id ROWS UNBOUNDED PRECEDING) - item_count AS cume_items_exclusive,
                SUM(item_count) OVER (ORDER BY pallet_id ROWS UNBOUNDED PRECEDING)              AS cume_items_inclusive
         FROM   #palettes)
SELECT S.shelf_id,
       S.size,
       number_of_items = ISNULL(P.item_count, 0),
       used = ISNULL(item_count, 0) - IIF(cume_items_inclusive > cume_shelf_capacity_inclusive, cume_items_inclusive - cume_shelf_capacity_inclusive, 0) --overspill to next shelves
            - IIF(cume_shelf_capacity_exclusive > cume_items_exclusive, cume_shelf_capacity_exclusive - cume_items_exclusive, 0), --stocked on previous shelves
       available = IIF(cume_shelf_capacity_inclusive < cume_items_inclusive, 0, ISNULL(cume_shelf_capacity_inclusive - cume_items_inclusive, S.size))
FROM   S
       LEFT JOIN P
         ON S.cume_shelf_capacity_inclusive > P.cume_items_exclusive
            AND S.cume_shelf_capacity_exclusive < P.cume_items_inclusive
ORDER BY shelf_id, 
         pallet_id;

【讨论】:

  • 哇!感谢您试用它
  • @TedFilippidis - 我个人觉得这是一个有趣的问题!
猜你喜欢
  • 2019-08-20
  • 2019-07-01
  • 2017-08-25
  • 2018-04-03
  • 1970-01-01
  • 1970-01-01
  • 2012-06-24
  • 2020-05-24
  • 2020-06-22
相关资源
最近更新 更多