将一个 table 中的项目数量分配给另一个 space 中的可用项目

Allocate number of items in one table to available space in another

我有两个表:

#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 有 space 20 件货品。等等。

让我们从一个简单的例子开始。有 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 |
+------------+------------+---------------------------+---------------------------+

如果

,托盘将(至少部分)放在货架上
  • 架子有 space - 即架子(和所有以前的架子)的容量大于以前所有调色板已经使用的 space。 cume size inclusive > cume item count exclusive
  • 托盘尚未完全拆包。 - 即所有先前货架的容量小于打开所有托盘(包括当前托盘)所需的 space。 cume size exclusive < 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;