我有两张桌子:
#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个物品的空间。等等。
答案 0 :(得分: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 > cume item count exclusive
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;