I have one table called INVENTORY which has data:
ITEM_NUM SUB_INV LOT_NUM QUANTITY LOT_EXPIRY_DATE 101 22 A1 10 9/29/2019 101 22 A2 14 9/28/2019
Let’s say, I have a request to fetch the quantity of 20 from these LOTs. As per the table, I have a total quantity available 24 (10 + 14). So I have enough quantity. I can take 10 Quantities from A1 and 10 from A2. But Instead, I have to look at the LOT_EXPIRY_DATE. Since A2 is expiring first, I shall take 14 quantities from A2 and then the rest of the quantities i.e. 6 from A1.
So below query works just fine:
SELECT lot_num, item_num, quantity, lot_expiry_date, CASE WHEN req_quantity >= rolling_qty THEN quantity ELSE req_quantity - LAG(rolling_qty) OVER( ORDER BY lot_expiry_date ) END AS qty_fetched FROM ( WITH base_inv_balance AS ( SELECT item_num, lot_num, quantity, lot_expiry_date FROM inventory WHERE item_num = '101' AND sub_inv = '22' ),requested_transaction AS ( SELECT '101' AS item_num, 20 AS req_quantity FROM dual ) SELECT base_inv_balance.item_num, base_inv_balance.lot_num, base_inv_balance.quantity, requested_transaction.req_quantity, base_inv_balance.lot_expiry_date, SUM(base_inv_balance.quantity) OVER( PARTITION BY base_inv_balance.item_num ORDER BY base_inv_balance.lot_expiry_date ) AS rolling_qty FROM base_inv_balance JOIN requested_transaction ON base_inv_balance.item_num = requested_transaction.item_num ORDER BY base_inv_balance.item_num, base_inv_balance.lot_expiry_date )
Result:
LOT_NUM ITEM_NUM QUANTITY LOT_EXPIRY_DATE QTY_FETCHED A2 101 14 9/28/2019 14 A1 101 10 9/29/2019 6
But if the requested quantity is 13, then the result is
LOT_NUM ITEM_NUM QUANTITY LOT_EXPIRY_DATE QTY_FETCHED A2 101 14 9/28/2019 null A1 101 10 9/29/2019 -1
Expected Result:
LOT_NUM ITEM_NUM QUANTITY LOT_EXPIRY_DATE QTY_FETCHED A2 101 14 9/28/2019 13 A1 101 10 9/29/2019 0
Is it possible to have a single query that can work well with both the quantities?
Need help with that query.
Advertisement
Answer
You want a cumulative sum and them some comparison logic:
select i.*, (case when running_quantity < 20 then quantity when running_quantity - quantity < 20 then 20 + quantity - running_quantity else 0 end) as qty_fetched from (select i.* sum(quantity) over (partition by item_num, sub_inv order by lot_expiry_date) as running_quantity from inventory i where item_num = 101 and sub_inv = 22 ) i;
Here is a db<>fiddle.