Please start any new threads on our new site at https://forums.sqlteam.com. We've got lots of great SQL Server experts to answer whatever question you can come up with.

 All Forums
 SQL Server 2000 Forums
 SQL Server Development (2000)
 Fulfillable Orders Query

Author  Topic 

AskSQLTeam
Ask SQLTeam Question

0 Posts

Posted - 2002-05-31 : 09:11:50
Jay writes "I have to create a fulfillable orders report, based on every line item for an order being fully in stock.

Simplified sample scenario: I have 1 widget currently on hand. Three people have ordered widgets overnight. Order #1 is for two widgets, orders #2 and #3 are for one widget each. Only order #2 should show up in the report, because order #1 is not completely fulfillable, and there are no widgets left for order #3 (orders ordered by OrderID)

In reality it it is slightly more complex than this, because orders generally consist of multiple products, and unless they're all in stock, an order shouldn't "claim" any of them.

After using some information obtained from this SQLTeam Article about calculating cumulative totals, I thought I had it solved, but all I managed to do was make my SQL server cry out for mercy.

I've tried using temporary tables, table variables, and cursors, in various combinations, with no luck thus far. Any ideas?"

JustinBigelow
SQL Gigolo

1157 Posts

Posted - 2002-05-31 : 09:51:03
It would help us (help you) if you post the DDE for your tables.

Justin

Go to Top of Page

joliver
Starting Member

13 Posts

Posted - 2002-06-05 : 11:36:33
My apologies for not including this information the first time. I hope this helps, as the solution still escapes me.

CREATE TABLE "Products" (
"ProductID" INT NOT NULL PRIMARY KEY,
"Product" VARCHAR(20) NOT NULL,
"Inventory" INT NOT NULL,
"Allocated" INT NOT NULL)

INSERT INTO Products VALUES (1, 'Widget', 1, 0)
INSERT INTO Products VALUES (2, 'Sprocket', 2, 0)
INSERT INTO Products VALUES (3, 'Gadget', 1, 0)

CREATE TABLE "Orders" (
"OrderID" INT NOT NULL PRIMARY KEY,
"DatePlaced" DATETIME NOT NULL)

INSERT INTO Orders VALUES (1, '5/1/2002 11:50 PM')
INSERT INTO Orders VALUES (2, '5/1/2002 11:51 PM')
INSERT INTO Orders VALUES (3, '5/1/2002 11:52 PM')
INSERT INTO Orders VALUES (4, '5/1/2002 11:53 PM')
INSERT INTO Orders VALUES (5, '5/1/2002 11:54 PM')
INSERT INTO Orders VALUES (6, '5/1/2002 11:55 PM')

CREATE TABLE "OrderDetails" (
"OrderDetailID" INT NOT NULL PRIMARY KEY,
"OrderID" INT NOT NULL,
"ProductID" INT NOT NULL,
"Quantity" INT NOT NULL)

INSERT INTO OrderDetails VALUES (1,1,1,2)
INSERT INTO OrderDetails VALUES (2,2,1,1)
INSERT INTO OrderDetails VALUES (3,3,1,1)
INSERT INTO OrderDetails VALUES (4,4,2,1)
INSERT INTO OrderDetails VALUES (5,4,3,3)
INSERT INTO OrderDetails VALUES (6,5,2,1)
INSERT INTO OrderDetails VALUES (7,5,3,1)
INSERT INTO OrderDetails VALUES (8,6,2,1)
INSERT INTO OrderDetails VALUES (9,6,3,1)



Order 1:
2 Widgets

Order 2:
1 Widget

Order 3:
1 Widget

Order 4:
1 Sprocket
3 Gadgets

Order 5:
1 Sprocket
1 Gadget

Order 6:
1 Sprocket
1 Gadget


Only orders 2 and 5 are fulfillable.

Order 1 can not be fulfilled because there is only one widget in stock.

Order 2 can be fulfilled, and that widget is now unavailable for other orders.

Order 3 can not be fulfilled because there was only one widget, and it's now
taken.

Order 4 can not be fulfilled because there are not 3 gadgets in stock.

Order 5 is fulfillable.

Order 6 is not fulfillable even though there is a sprocket left.

It may be assumed that ordering by OrderID or DatePlaced will result in the same
order.

The mechanism by which orders are flagged as fulfillable and inventory is
accounted for is still up in the air, for the purposes of this discussion,
Products.Allocated can be assumed to hold this number if this is beneficial, and
the method of flagging orders may be assumed to be the ability to generate a
select statement that will encompass them, and only them. However, these are
very open to suggestion at the moment, and don't hesitate if you see a
suggestion that may make this easier.


Go to Top of Page

joliver
Starting Member

13 Posts

Posted - 2002-06-10 : 16:19:44
Does anyone perchance have any insight into this query? I'm still struggling. Would really appreciate any insight at all.

Go to Top of Page

robvolk
Most Valuable Yak

15732 Posts

Posted - 2002-06-10 : 16:25:17
Just a quick stab, see if this helps:

http://www.sqlteam.com/forums/topic.asp?TOPIC_ID=10177

Go to Top of Page

Page47
Master Smack Fu Yak Hacker

2878 Posts

Posted - 2002-06-10 : 18:18:44
Here I was waiting for Celko to chime in with his explanation of the Codd's Temporal Join . . . little did I know 'Dirk Diggler' was gonna take a 'quick stab' at it . . . . . .

At first blush, I think joliver already has the OrdersDetails. He needs figure how to fill the most orders with the limited quantity he currently has.

This reminds me an awful lot of a conference venue allocation problem we went through a while back. Fribble and SetBased were going down the right path and jcelko chimed in with one of his the-answer-to-this-is-in-my-book posts . . . I've been trying to port the solution there but I can't seem to get it.

The iterative solution is pretty easy, yeah? But a set based method or at least intelligent-iterative one seems to be a bit more elusive.

<O>
Go to Top of Page

Tigger
Yak Posting Veteran

85 Posts

Posted - 2002-06-10 : 20:09:21
OK, I THINK I have a solution. It works for the example given but will
need some thorough testing !!

 DECLARE @Min_Order INT

-- create temporary table to hold order id and filled status (N=No, Y=Yes, X=Can't be filled)
DROP TABLE #TempTable
CREATE TABLE #TempTable (OrderId INT, Filled CHAR(1))

-- insert orders into temp table, set filled to 'N'
INSERT INTO #TempTable
SELECT OrderId, 'N'
FROM ORDERS

-- for those orders where insufficient quantities available, set filled status to 'X'
UPDATE #TempTable
SET Filled = 'X'
FROM #TempTable T
JOIN OrderDetails OD
ON T.OrderId = OD.OrderId
JOIN Products P
ON OD.ProductId = P.ProductId
WHERE T.Filled = 'N'
AND OD.Quantity > (P.Inventory - P.Allocated)

-- loop through remaining unfilled orders
WHILE EXISTS (SELECT * FROM #TempTable WHERE Filled = 'N')
BEGIN
-- get order id of first unfilled order
SELECT @Min_Order = (SELECT MIN(OrderId) FROM #TempTable WHERE Filled = 'N')

-- update allocated field of products table for order
UPDATE Products
SET Allocated = O.Quantity + P.Allocated
FROM Products P
JOIN OrderDetails O
ON P.ProductId = O.ProductId
WHERE O.OrderId = @Min_Order

-- set filled status to 'Y'
UPDATE #TempTable
SET Filled = 'Y'
WHERE OrderId = @Min_Order

-- for those remaining orders where insufficient quantities available, set filled status to 'X'
UPDATE #TempTable
SET Filled = 'X'
FROM #TempTable T
JOIN OrderDetails OD
ON T.OrderId = OD.OrderId
JOIN Products P
ON OD.ProductId = P.ProductId
WHERE T.Filled = 'N'
AND OD.Quantity > (P.Inventory - P.Allocated)

END

SELECT * FROM #TempTable



Basically, it discounts any orders straight away where there are not
enough of each product to satisfy them.

It then deals with the first order which can be satisfied and updates the allocated fields, then discounts any remaining order where there are not enough of each product left to satisfy them. and loops through until all orders are either filled or can't be filled.


Go to Top of Page

byrmol
Shed Building SQL Farmer

1591 Posts

Posted - 2002-06-10 : 21:47:16
Here is a untested stab at a set solution....


Select Distinct O.OrderID,
Case sign(OD.Quantity - (Select sum(Quantity)
from Orders O1
inner join OrderDetails OD1 on O1.OrderID = OD1.OrderID
where OD1.ProductID = P.ProductID and O.DatePlaced >= O1.DatePlaced
and not exists (Select O.OrderID
from Orders O
inner join OrderDetails OD on O.OrderID = OD.OrderID
Inner join Products P on P.ProductID = OD.ProductID
where Quantity > Inventory and O.OrderID = O1.OrderID
group by O.OrderID )))
when 1 then 'Fillable'
when 0 then 'Fillable'
else 'Not Fillable'
end as Status
from Orders O
inner join OrderDetails OD on O.OrderID = OD.OrderID
Inner join Products P on P.ProductID = OD.ProductID


DavidM

"SQL-3 is an abomination.."
Go to Top of Page
   

- Advertisement -