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.
| 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 |
 |
|
|
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 WidgetsOrder 2: 1 Widget Order 3: 1 Widget Order 4: 1 Sprocket 3 Gadgets Order 5: 1 Sprocket 1 GadgetOrder 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. |
 |
|
|
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. |
 |
|
|
robvolk
Most Valuable Yak
15732 Posts |
|
|
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> |
 |
|
|
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 willneed 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 #TempTableCREATE TABLE #TempTable (OrderId INT, Filled CHAR(1)) -- insert orders into temp table, set filled to 'N' INSERT INTO #TempTableSELECT OrderId, 'N'FROM ORDERS-- for those orders where insufficient quantities available, set filled status to 'X'UPDATE #TempTableSET Filled = 'X'FROM #TempTable TJOIN OrderDetails ODON T.OrderId = OD.OrderIdJOIN Products PON OD.ProductId = P.ProductIdWHERE T.Filled = 'N'AND OD.Quantity > (P.Inventory - P.Allocated)-- loop through remaining unfilled ordersWHILE 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)ENDSELECT * FROM #TempTable Basically, it discounts any orders straight away where there are notenough 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. |
 |
|
|
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 Statusfrom Orders Oinner join OrderDetails OD on O.OrderID = OD.OrderIDInner join Products P on P.ProductID = OD.ProductID DavidM"SQL-3 is an abomination.." |
 |
|
|
|
|
|
|
|