I've been trying to get the simplest way to get a query from different tables, but only showing the quantity according to another table
-- I want to create a Pickroute Report -- the pickroute will have an idorder, article, quantity and location
-- If I have an order that needs 25 ITEM01 -- I will take 10 from LOC01 and 15 from LOC02 -- All the locatios have a sequence -- Once I complete the 25 I need to update the IDORDER column in SPLITTABLE
Let me explain
I have the following tables
SALESORDER table:
IDORDER ARTICLE QUANTITY
----------------------------
1 ITEM01 25
1 ITEM02 10
2 ITEM01 20
3 ITEM01 5
3 ITEM03 4
INVENTORY table:
ARTICLE QUANTITY LOCATION SEQUENCE
---------------------------------------
ITEM01 10 LOC01 1
ITEM01 30 LOC02 2
ITEM01 30 LOC03 3
ITEM02 2 LOC02 2
ITEM02 10 LOC03 3
ITEM03 1 LOC01 1
ITEM03 5 LOC02 2
What I am trying to get is the following
OPORDER table:
ARTICLE QUANTITY LOCATION IDORDER
----------------------------------------
ITEM01 10 LOC01 1
ITEM01 15 LOC02 1
ITEM02 2 LOC02 1
ITEM02 8 LOC03 1
ITEM01 15 LOC02 2
ITEM01 5 LOC03 2
ITEM01 5 LOC03 3
ITEM03 1 LOC01 3
ITEM03 4 LOC02 3
Now let me show you what I'm doing to get it done (at least trying to do it).
Schema :
SALESORDER
DROP TABLE IF EXISTS SALESORDER
CREATE TABLE SALESORDER
(
IDORDER INT,
ARTICLE VARCHAR(50),
QUANTITY INT
);
INSERT SALESORDER (IDORDER, ARTICLE, QUANTITY)
VALUES (1, 'ITEM01', 25), (1, 'ITEM02', 10),
(2, 'ITEM01', 20), (3, 'ITEM01', 5),
(3, 'ITEM03', 4)
INVENTORY
DROP TABLE IF EXISTS INVENTORY
CREATE TABLE INVENTORY
(
ARTICLE VARCHAR(50),
QUANTITY INT,
LOCATION VARCHAR(50),
SEQUENCE INT
);
INSERT INVENTORY (ARTICLE, QUANTITY,LOCATION,SEQUENCE)
VALUES ('ITEM01', 10, 'LOC01',1), ('ITEM01', 30, 'LOC02',2),
('ITEM01', 30, 'LOC03',3), ('ITEM02', 2, 'LOC02',2),
('ITEM02', 10, 'LOC03',3), ('ITEM03', 1, 'LOC01',1),
('ITEM03', 5, 'LOC02',2)`
What I'm doing is:
first split into one piece table from the inventory
SPLITTABLE
DROP TABLE IF EXISTS SPLITTABLE
CREATE TABLE SPLITTABLE
(
ARTICLE VARCHAR(50),
QUANTITY INT,
LOCATION VARCHAR(50),
IDORDER INT,
SEQUENCE INT
);
SPLIT
WITH RTE (Vals) AS
(
SELECT 1
UNION ALL
SELECT 1 + Vals
FROM RTE
WHERE Vals < 500
)
INSERT INTO SPLITTABLE (ARTICLE, QUANTITY, LOCATION, IDORDER,SEQUENCE)
SELECT ARTICLE,1 AS QUANTITY,LOCATIONS,0 AS IDORDER, SEQUENCE
FROM INVENTORY INV
INNER JOIN RTE R ON R.Vals <= INV.Quantity
OPTION (maxrecursion 0);
--Result
88 rows with quantity 1 --88 Because ITEM01 70 ITEM02 12 and ITEM03 6
SELECT * FROM SPLITTABLE
ARTICLE QUANTITY LOCATION IDORDER SEQUENCE
ITEM01 1 LOC01 0 1
ITEM01 1 LOC02 0 2
ITEM01 1 LOC03 0 3
ITEM02 1 LOC02 0 2
ITEM02 1 LOC03 0 3
ITEM03 1 LOC01 0 1
ITEM03 1 LOC02 0 2
ITEM01 1 LOC01 0 1
ITEM01 1 LOC02 0 2
... until 88 rows(IDORDER is in 0 because it is not asigned yet)
After split I assign an Idorder(On the declare statements this is what I want to avoid)
DECLARE @LIMIT INT =25;
DECLARE @ORDER INT = 1;
DECLARE @ARTICLE VARCHAR(50)='ITEM01';
WITH CTE AS
(
SELECT
ARTICLE, QUANTITY, LOCATION, IDORDER,
RUNNINGTOTAL = SUM(QUANTITY) OVER (PARTITION BY ARTICLE ORDER BY
LOCATION
ROWS UNBOUNDED PRECEDING)
FROM
SPLITTABLE
WHERE
ARTICLE = @ARTICLE AND IDORDER =0
), TOTAL AS
(
SELECT
ARTICLE, QUANTITY, LOCATION, IDORDER = @ORDER
FROM
CTE
WHERE
RUNNINGTOTAL <= @LIMIT
)
UPDATE CTE
SET IDORDER = T.IDORDER
FROM TOTAL AS T
WHERE RUNNINGTOTAL <= @LIMIT;
--Result
25 rows from SPLITTABLE with ITEM01 marked as IDORDER 1
SELECT * FROM SPLITTABLE WHERE ARTICLE ='ITEM01' ORDER BY SEQUENCE ASC
ARTICLE QUANTITY LOCATION IDORDER SEQUENCE
ITEM01 1 LOC01 1 1
ITEM01 1 LOC01 1 1
ITEM01 1 LOC01 1 1
ITEM01 1 LOC01 1 1
ITEM01 1 LOC01 1 1
ITEM01 1 LOC01 1 1
ITEM01 1 LOC01 1 1
ITEM01 1 LOC01 1 1
ITEM01 1 LOC01 1 1
ITEM01 1 LOC01 1 1
ITEM01 1 LOC02 1 2
ITEM01 1 LOC02 1 2
ITEM01 1 LOC02 1 2
ITEM01 1 LOC02 1 2
ITEM01 1 LOC02 1 2
ITEM01 1 LOC02 1 2
ITEM01 1 LOC02 1 2
ITEM01 1 LOC02 1 2
ITEM01 1 LOC02 1 2
ITEM01 1 LOC02 1 2
ITEM01 1 LOC02 1 2
ITEM01 1 LOC02 1 2
ITEM01 1 LOC02 1 2
ITEM01 1 LOC02 1 2
ITEM01 1 LOC02 1 2
-- The rest of the rows are in 0 because I only select ITEM01 and quantity 25 it --takes only 10 from the LOC01(sequence 1) and 15 from LOC02(sequence 2)
--After changing all the declare statements for each item, order and quantity I can see the result
--With this query you get what I want
SELECT ARTICLE,SUM(QUANTITY) AS QUANTITY,LOCATION,IDORDER FROM SPLITTABLE
WHERE IDORDER<>0 GROUP BY ARTICLE,IDORDER,LOCATION ORDER BY IDORDER ASC
With these queries I get the information I need but I have some problems
The split part takes all the articles into the SPLITTABLE
the problem is when I have an order asking for 1 article but in the inventory for that article has > 1000 it takes a lot of time and resources
Once the split is done, I assign idorder
but I had to do it manually for each article and each order
I have to thank you in advance for all your comments and help
In case you need more information, let me know
You can use cursors.
I used table variables in the example so you'll have to change a code a little bit (remove @)
When there is not enough items in the inventory the NULL will be inserted into the LOCATION column, remove this if necessary.
I didn't add quantity limit, you'll have to make sure that the order can't contain more than the limit because it seems misleading to let the customer order more and then send less than he ordered. Unless I misunderstood the intent.
DECLARE @SALESORDER TABLE
(
IDORDER INT,
ARTICLE VARCHAR(50),
QUANTITY INT
);
INSERT @SALESORDER (IDORDER, ARTICLE, QUANTITY)
VALUES (1, 'ITEM01', 25), (1, 'ITEM02', 10),(1, 'ITEM14', 1),(2, 'ITEM00', 10),
(2, 'ITEM01', 70), (3, 'ITEM01', 5),
(3, 'ITEM03', 4)
DECLARE @INVENTORY TABLE
(
ARTICLE VARCHAR(50),
QUANTITY INT,
LOCATION VARCHAR(50)
);
INSERT @INVENTORY (ARTICLE, QUANTITY,LOCATION)
VALUES ('ITEM01', 10, 'LOC01'), ('ITEM01', 30, 'LOC02'),
('ITEM01', 30, 'LOC03'), ('ITEM02', 2, 'LOC02'),
('ITEM02', 10, 'LOC03'), ('ITEM03', 1, 'LOC01'),
('ITEM03', 5, 'LOC02'), ('ITEM01', 0, 'LOC04')
DECLARE @SPLITTABLE TABLE
(
ARTICLE VARCHAR(50),
QUANTITY INT,
LOCATION VARCHAR(50),
IDORDER INT
);
---------------------------------------------------------------------------
DECLARE so_cur CURSOR local fast_forward
FOR
SELECT so.ARTICLE,so.QUANTITY,so.IDORDER FROM @SALESORDER as so
ORDER BY so.ARTICLE,so.IDORDER
;
DECLARE inv_cur CURSOR local fast_forward
FOR
SELECT inv.ARTICLE,inv.QUANTITY,inv.[LOCATION] FROM @INVENTORY as inv
ORDER BY inv.ARTICLE,inv.[LOCATION]
;
declare @so_ARTICLE varchar(50);
declare @so_QUANTITY int;
declare @so_IDORDER int;
declare @inv_ARTICLE varchar(50);
declare @inv_QUANTITY int;
declare @inv_LOCATION varchar(50);
declare @nextOrder bit = 1;
declare @nextInv bit = 1;
declare @outOfInv bit = 0;
open so_cur
open inv_cur
WHILE 1=1
BEGIN
IF @nextOrder = 1
BEGIN
FETCH NEXT from so_cur
INTO
@so_ARTICLE,
@so_QUANTITY,
@so_IDORDER
;
SET @nextOrder = 0;
if @@FETCH_STATUS = -1 break;
END
IF @outOfInv = 0 AND @nextInv = 1
BEGIN
FETCH NEXT from inv_cur
INTO
@inv_ARTICLE,
@inv_QUANTITY,
@inv_LOCATION
;
SET @nextInv = 0;
if @@FETCH_STATUS = -1
BEGIN
SET @outOfInv = 1;
PRINT N'NOT ENOUGH ITEMS IN INVENTORY'
END
END
IF @outOfInv = 0 AND @inv_ARTICLE < @so_ARTICLE
BEGIN
SET @nextInv = 1;
END
ELSE IF @outOfInv = 1 OR @inv_ARTICLE > @so_ARTICLE
BEGIN
PRINT N'NOT ENOUGH ITEMS IN INVENTORY, YOU MIGHT WANT TO INSERT LOCATION=NULL TO THE SPLITTABLE';
INSERT INTO @SPLITTABLE (ARTICLE,QUANTITY,LOCATION,IDORDER) VALUES (@so_ARTICLE,@so_QUANTITY,NULL,@so_IDORDER)
SET @nextOrder = 1;
END
ELSE
BEGIN
IF @so_QUANTITY < @inv_QUANTITY
BEGIN
IF @so_QUANTITY >0
BEGIN
INSERT INTO @SPLITTABLE (ARTICLE,QUANTITY,LOCATION,IDORDER) VALUES (@so_ARTICLE,@so_QUANTITY,@inv_LOCATION,@so_IDORDER)
SET @inv_QUANTITY -= @so_QUANTITY
END
SET @nextOrder = 1;
END
ELSE IF @so_QUANTITY = @inv_QUANTITY
BEGIN
IF @so_QUANTITY >0
BEGIN
INSERT INTO @SPLITTABLE (ARTICLE,QUANTITY,LOCATION,IDORDER) VALUES (@so_ARTICLE,@so_QUANTITY,@inv_LOCATION,@so_IDORDER)
END
SET @nextOrder = 1;
SET @nextInv = 1;
END
ELSE
BEGIN
IF @inv_QUANTITY >0
BEGIN
INSERT INTO @SPLITTABLE (ARTICLE,QUANTITY,LOCATION,IDORDER) VALUES (@so_ARTICLE,@inv_QUANTITY,@inv_LOCATION,@so_IDORDER)
SET @so_QUANTITY -= @inv_QUANTITY
END
SET @nextInv = 1;
END
END
END
CLOSE so_cur;
DEALLOCATE so_cur;
CLOSE inv_cur;
DEALLOCATE inv_cur;
-----------------------------------------------------------------------
SELECT * FROM @SPLITTABLE ORDER BY IDORDER,ARTICLE
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.