By using db<>fiddle, you agree to license everything you submit by Creative Commons CC0.
CREATE TABLE inventory (
SKU INT,
TransactionType VARCHAR(32),
WarehouseCode VARCHAR(32),
TransactionDate DATE,
Qty INT
)
INSERT INTO
inventory
VALUES
(100, 'IN', 'WH1', '2021-04-30', 100),
(100, 'IN', 'WH2', '2021-04-30', 50),
(101, 'IN', 'WH1', '2021-04-30', 30),
(101, 'IN', 'WH2', '2021-05-01', 25),
(100, 'OUT', 'WH2', '2021-05-02', 30),
(100, 'OUT', 'WH1', '2021-05-02', 20),
(100, 'OUT', 'WH1', '2021-05-04', 50),
(100, 'OUT', 'WH2', '2021-05-04', 20),
(100, 'OUT', 'WH1', '2021-05-05', 25),
(100, 'IN', 'WH2', '2021-05-10', 30),
(100, 'IN', 'WH1', '2021-05-11', 30),
(101, 'OUT', 'WH2', '2021-05-12', 20),
(100, 'OUT', 'WH1', '2021-05-15', 30),
(100, 'IN', 'WH1', '2021-05-16', 30),
(102, 'IN', 'WH1', '2021-05-15', 25),
(102, 'OUT', 'WH1', '2021-05-17', 2),
(102, 'ADJ', 'WH1', '2021-05-18', 5),
(102, 'ADJ', 'WH1', '2021-05-18', -1);
SELECT * FROM inventory
ORDER BY WarehouseCode, SKU, TransactionDate
;
SKU | TransactionType | WarehouseCode | TransactionDate | Qty |
---|---|---|---|---|
100 | IN | WH1 | 2021-04-30 | 100 |
100 | OUT | WH1 | 2021-05-02 | 20 |
100 | OUT | WH1 | 2021-05-04 | 50 |
100 | OUT | WH1 | 2021-05-05 | 25 |
100 | IN | WH1 | 2021-05-11 | 30 |
100 | OUT | WH1 | 2021-05-15 | 30 |
100 | IN | WH1 | 2021-05-16 | 30 |
101 | IN | WH1 | 2021-04-30 | 30 |
102 | IN | WH1 | 2021-05-15 | 25 |
102 | OUT | WH1 | 2021-05-17 | 2 |
102 | ADJ | WH1 | 2021-05-18 | 5 |
102 | ADJ | WH1 | 2021-05-18 | -1 |
100 | IN | WH2 | 2021-04-30 | 50 |
100 | OUT | WH2 | 2021-05-02 | 30 |
100 | OUT | WH2 | 2021-05-04 | 20 |
100 | IN | WH2 | 2021-05-10 | 30 |
101 | IN | WH2 | 2021-05-01 | 25 |
101 | OUT | WH2 | 2021-05-12 | 20 |
WITH
cumulative AS
(
SELECT
*,
SUM(CASE WHEN TransactionType = 'IN' THEN Qty ELSE 0 END)
OVER (
PARTITION BY SKU, WarehouseCode
ORDER BY TransactionDate
)
AS qty_in_so_far,
SUM(CASE WHEN TransactionType = 'OUT' THEN Qty ELSE 0 END)
OVER (
PARTITION BY SKU, WarehouseCode
)
AS qty_out_final
FROM
inventory
)
SELECT
*,
CASE WHEN qty_out_final > qty_in_so_far THEN 0
WHEN qty_in_so_far - qty_out_final > qty THEN qty
ELSE qty_in_so_far - qty_out_final END AS qty_final,
DATEDIFF(day, TransactionDate, '2021-05-20') + 1 AS aging
FROM
cumulative
WHERE
TransactionType = 'IN'
ORDER BY
TransactionDate,
SKU,
WarehouseCode
SKU | TransactionType | WarehouseCode | TransactionDate | Qty | qty_in_so_far | qty_out_final | qty_final | aging |
---|---|---|---|---|---|---|---|---|
100 | IN | WH1 | 2021-04-30 | 100 | 100 | 125 | 0 | 21 |
100 | IN | WH2 | 2021-04-30 | 50 | 50 | 50 | 0 | 21 |
101 | IN | WH1 | 2021-04-30 | 30 | 30 | 0 | 30 | 21 |
101 | IN | WH2 | 2021-05-01 | 25 | 25 | 20 | 5 | 20 |
100 | IN | WH2 | 2021-05-10 | 30 | 80 | 50 | 30 | 11 |
100 | IN | WH1 | 2021-05-11 | 30 | 130 | 125 | 5 | 10 |
102 | IN | WH1 | 2021-05-15 | 25 | 25 | 2 | 23 | 6 |
100 | IN | WH1 | 2021-05-16 | 30 | 160 | 125 | 30 | 5 |
SELECT i.*
, SUM(CASE WHEN TransactionType = 'IN' THEN 1 ELSE 0 END) OVER (PARTITION BY SKU, WarehouseCode ORDER BY TransactionDate) AS grp
FROM inventory AS i
WHERE TransactionType IN ('IN', 'ADJ')
ORDER BY WarehouseCode, SKU, TransactionDate
;
SKU | TransactionType | WarehouseCode | TransactionDate | Qty | grp |
---|---|---|---|---|---|
100 | IN | WH1 | 2021-04-30 | 100 | 1 |
100 | IN | WH1 | 2021-05-11 | 30 | 2 |
100 | IN | WH1 | 2021-05-16 | 30 | 3 |
101 | IN | WH1 | 2021-04-30 | 30 | 1 |
102 | IN | WH1 | 2021-05-15 | 25 | 1 |
102 | ADJ | WH1 | 2021-05-18 | 5 | 1 |
102 | ADJ | WH1 | 2021-05-18 | -1 | 1 |
100 | IN | WH2 | 2021-04-30 | 50 | 1 |
100 | IN | WH2 | 2021-05-10 | 30 | 2 |
101 | IN | WH2 | 2021-05-01 | 25 | 1 |
WITH cte1 AS (
SELECT i.*
, ROW_NUMBER() OVER (PARTITION BY SKU, WarehouseCode ORDER BY TransactionDate) AS n
, SUM(CASE WHEN TransactionType = 'IN' THEN 1 ELSE 0 END) OVER (PARTITION BY SKU, WarehouseCode ORDER BY TransactionDate) AS grp
FROM inventory AS i
WHERE TransactionType IN ('IN', 'ADJ')
)
SELECT SKU, WarehouseCode, grp
, MIN(TransactionDate) AS TransactionDate
, SUM(Qty) AS Qty
FROM cte1
GROUP BY WarehouseCode, SKU, grp
ORDER BY WarehouseCode, SKU, TransactionDate
;
SKU | WarehouseCode | grp | TransactionDate | Qty |
---|---|---|---|---|
100 | WH1 | 1 | 2021-04-30 | 100 |
100 | WH1 | 2 | 2021-05-11 | 30 |
100 | WH1 | 3 | 2021-05-16 | 30 |
101 | WH1 | 1 | 2021-04-30 | 30 |
102 | WH1 | 1 | 2021-05-15 | 29 |
100 | WH2 | 1 | 2021-04-30 | 50 |
100 | WH2 | 2 | 2021-05-10 | 30 |
101 | WH2 | 1 | 2021-05-01 | 25 |
WITH cte1 AS (
SELECT i.*
, SUM(CASE WHEN TransactionType = 'IN' THEN 1 ELSE 0 END) OVER (PARTITION BY SKU, WarehouseCode ORDER BY TransactionDate) AS grp
FROM inventory AS i
WHERE TransactionType IN ('IN', 'ADJ')
)
, cte2 AS (
SELECT SKU, WarehouseCode, 'IN' AS TransactionType
, MIN(TransactionDate) AS TransactionDate
, SUM(Qty) AS Qty
FROM cte1
GROUP BY WarehouseCode, SKU, grp
UNION
SELECT SKU, WarehouseCode, TransactionType, TransactionDate, Qty
FROM inventory
WHERE TransactionType = 'OUT'
)
SELECT *
FROM cte2
ORDER BY WarehouseCode, SKU, TransactionDate
;
SKU | WarehouseCode | TransactionType | TransactionDate | Qty |
---|---|---|---|---|
100 | WH1 | IN | 2021-04-30 | 100 |
100 | WH1 | OUT | 2021-05-02 | 20 |
100 | WH1 | OUT | 2021-05-04 | 50 |
100 | WH1 | OUT | 2021-05-05 | 25 |
100 | WH1 | IN | 2021-05-11 | 30 |
100 | WH1 | OUT | 2021-05-15 | 30 |
100 | WH1 | IN | 2021-05-16 | 30 |
101 | WH1 | IN | 2021-04-30 | 30 |
102 | WH1 | IN | 2021-05-15 | 29 |
102 | WH1 | OUT | 2021-05-17 | 2 |
100 | WH2 | IN | 2021-04-30 | 50 |
100 | WH2 | OUT | 2021-05-02 | 30 |
100 | WH2 | OUT | 2021-05-04 | 20 |
100 | WH2 | IN | 2021-05-10 | 30 |
101 | WH2 | IN | 2021-05-01 | 25 |
101 | WH2 | OUT | 2021-05-12 | 20 |
WITH cte1 AS (
SELECT i.*
, SUM(CASE WHEN TransactionType = 'IN' THEN 1 ELSE 0 END) OVER (PARTITION BY SKU, WarehouseCode ORDER BY TransactionDate) AS grp
FROM inventory AS i
WHERE TransactionType IN ('IN', 'ADJ')
)
, cte2 AS (
SELECT SKU, WarehouseCode, 'IN' AS TransactionType
, MIN(TransactionDate) AS TransactionDate
, SUM(Qty) AS Qty
FROM cte1
GROUP BY WarehouseCode, SKU, grp
UNION
SELECT SKU, WarehouseCode, TransactionType, TransactionDate, Qty
FROM inventory
WHERE TransactionType = 'OUT'
)
, cumulative AS (
SELECT *
, SUM(CASE WHEN TransactionType = 'OUT' THEN Qty ELSE 0 END) OVER (PARTITION BY SKU, WarehouseCode) AS qty_out_final
, SUM(CASE WHEN TransactionType = 'IN' THEN Qty ELSE 0 END) OVER (PARTITION BY SKU, WarehouseCode ORDER BY TransactionDate) AS qty_in_so_far
FROM cte2
)
SELECT SKU, WarehouseCode, TransactionType, TransactionDate
, qty_out_final, qty_in_so_far, Qty
, CASE WHEN qty_out_final >= qty_in_so_far THEN 0
ELSE qty_in_so_far - qty_out_final END AS qty_final
, DATEDIFF(day, TransactionDate, '2021-05-20') + 1 AS aging
FROM cumulative
WHERE TransactionType = 'IN'
ORDER BY TransactionDate, SKU, WarehouseCode
;
SKU | WarehouseCode | TransactionType | TransactionDate | qty_out_final | qty_in_so_far | Qty | qty_final | aging |
---|---|---|---|---|---|---|---|---|
100 | WH1 | IN | 2021-04-30 | 125 | 100 | 100 | 0 | 21 |
100 | WH2 | IN | 2021-04-30 | 50 | 50 | 50 | 0 | 21 |
101 | WH1 | IN | 2021-04-30 | 0 | 30 | 30 | 30 | 21 |
101 | WH2 | IN | 2021-05-01 | 20 | 25 | 25 | 5 | 20 |
100 | WH2 | IN | 2021-05-10 | 50 | 80 | 30 | 30 | 11 |
100 | WH1 | IN | 2021-05-11 | 125 | 130 | 30 | 5 | 10 |
102 | WH1 | IN | 2021-05-15 | 2 | 29 | 29 | 27 | 6 |
100 | WH1 | IN | 2021-05-16 | 125 | 160 | 30 | 35 | 5 |